Quite many of the PA mods do not keep their local variables local, but they are polluting the global namespace. When you input window into the debugger console when a game is running, you will see tens of variables that leak the internal state of some mods ($leftPanel, $middlePanel, $rightPanel, EnergyKilo, Energy_Ratio, Metal_Net, Metal_Ratio, ReportData, ReportPlayer, ReportTeam, ReportedPlanet, RunningGameData, StatsReportData, ValueChangeAccumulator, actionsSinceLastTick, addDeatchListener, addedDeathListener, allow_console, apmCnt, apply_keybinds, apply_keybindsHotbuild, callServerTime, checkPaStatsVersion, cleanupLegacyStorage, clientInformation, closed, commanderImages... the list goes on and on) and some of them are so common words that a naming conflict with some other mod is just a matter of time (b, c, length, i, name, screenX, screenY, status etc.) which may cause weird bugs when those conflicting mods are used together. In JavaScript the only way of scoping variables is the function scope. The way to isolate your variables is to use the JavaScript Module Pattern: put the variables and functions inside an anonymous function which you invoke right away. If there are some variables or functions that you want to expose for others to call, then put them into an object, return that object from the method and assign it to a global variable - the only global variable that your program creates - which will work as a namespace for your variables. For example like this: Code: var pamentor = (function () { // no outsider will see these variables and functions function cannotCallThis() {} var cannotTouchThis = 0; // all publicly exposed variables and functions need to be made members of this object var pamentor = {}; pamentor.stats = ko.observable({}); return pamentor; })(); For operations that manipulate the DOM, you can pass the function to jQuery's $ like this: Code: $(function () { function loadTemplate(element, url) { element.load(url, function () { ko.applyBindings(model, element.get(0)); }); } // making that abovementioned object visible to Knockout model.pamentor = pamentor; // some more bootstrap code setInterval(pamentor.updateClock, 1000); setInterval(pamentor.updateStats, 5000); // manipulating the DOM, must be done after the document is ready createFloatingFrame('pa_mentor_frame', 100, 100, {'offset': 'leftCenter', 'left': 0}); loadTemplate($('#pa_mentor_frame_content'), 'coui://ui/mods/PAMentor/live_game/pa_mentor.html'); }); This way your mod will not accidentally conflict with the variables from other mods, and others can access only those variables and functions that you explicitly expose. For example the pamentor.stats variable in the first code example can be accessed by others, but the loadTemplate function in the second cannot be accessed by anyone else.
After chargrove recommanded it I just got my copy of Javascript: The good parts. A good book that opened my eyes to this issue as well. EDIT: Why use jqueries $(...) though? The mod code is run by the ui mod system of PA that runs within some on document load callback already, so I dont think it matters.
Oh, that's pretty neat. I just prepended everything I declared with "dNotes_" for my Notes mod to avoid conflicts. I was wondering why cola_colin had done stuff like that with his PA stats mod when I was trying to make my mod compatible with his.
When I saw those I thought "who would use such names in a global namespace" Turns out I did. Those are temp variables that are used as a part of the PA Stats loading process. I assumed Javascript has a block scope. Turns out it has not. xD If somebody overwrites those values PA Stats won't suffer though.
Could run mods through jslint. Would provide a second set of eyes and show implied global variables. jslint.com jslint.com/lint.html - instructions
I use jshint.com don't know if there is much difference with jslint. I use some copied and modified code from uber and jshint doesn't like it bye the way But great tip anyhow.
Oh for crying out loud. Guys I *barely* scraped a pass in programming engineering year 1, and the very first thing we were told was to avoid global variables like the plague! (May have been one of the/the main contributing factor why I barely scraped a pass)
The issue is that javascript makes it actually hard to prevent them. It is based on them and the missing block scope while having the typical scope syntax makes it even less obvious. Without first reading up on a good book it is very easy to go "ah I know this syntax and it seems to work" until you end up with a bunch of surprises.
jslint is developed by Douglas Crockford the author of JavaScript: the good parts. It's rather brutal in its quality checking but it shows all global variables.