Does javascript/jquery "hate" negative number as part of id name? - javascript

I have a snippet of JQuery code that do some bar scrolling.
Since I have three, four, ... n bar to slide into my PHP page, I assign them dinamically an id and pass it to JQuery for be sure that my snippet slide the correct bar on a mouseOver event.
That's the snippet of code that do the "inizialization" of my scrolls
(function($){
$.fn.horizontalScroll = function(options) {
var rid = arguments[0];
var oid = arguments[1];
var defaults = { };
var options = $.extend(defaults, options);
return this.each(function() {
var horiz_scroll = new dw_scrollObj($(this).attr('id'), $(this).children().attr('id'), $(this).children().children().attr('id'));
horiz_scroll.setUpScrollbar("dragBar_"+rid+"_offer_"+oid, "track_"+rid+"_offer_"+oid, "h", 1, 1);
horiz_scroll.setUpScrollControls('scrollbar_'+rid+'_offer_'+oid);
As you can see, "dragBar_"+rid+"_offer_"+oid dinamically concatenates my id(s) to other string part.
That's fine and all goin' well, except when my oid became something like -1
In that case I have an error that says
identifier starts immediately after numeric literal
That's confuse me, because i've read on StackOverflow some questions like this (just a random one) and I expect that behaviour for all concatenation that involves number.
That the snippet of code where all "breaks"
this.timerId = setInterval(this.animString + ".scroll()", 10);
Where this.animString is "dw_scrollObj.col.horiz_container_outer_55_offer_-1" while in other case (where it works) is "dw_scrollObj.col.horiz_container_outer_62_offer_234"
Anyone can explain me why this happen?

You are trying to access a global variable named dw_scrollObj.col.horiz_container_outer_55_offer_-1. Some browsers will make all elements accessible by their ID like that, but it's not recommended.
The reason it doesn't work in your specific case is that what you've written is not a valid javascript variable name. Your attempt to access a variable will be interpreted as
dw_scrollObj.col.horiz_container_outer_55_offer_ - 1
If you would instead access your object by
document.getElementById('dw_scrollObj.col.horiz_container_outer_55_offer_-1')
or
$('#dw_scrollObj.col.horiz_container_outer_55_offer_-1')
you would not have this same problem.
For your setInterval code, that would mean
this.timerId = setInterval("$('#" + this.animString + "').scroll()", 10);
or preferably
this.timerId = setInterval(function() {
$('#' + this.animString).scroll();
}, 10);
If your code is in a loop, where animString will change over time, inside the context, you will need to create a new closure:
this.timerId = setInterval((function(x) {
return function() {
$('#'+x).scroll();
};
})(this.animString), 10);

Your setInterval snippet breaks because the string you pass to setInterval is evaluated as JavaScript. It becomes
dw_scrollObj.col.horiz_container_outer_55_offer_-1.scroll()
but a hyphen (-) is not valid in identifiers.
E.g. this throws an error
var some-name = 'foo';

Related

Create a re-usable type writer effect function in Javascript?

I know the basics of what I need to do here, but my attempt at coding it is riddled with problems so here is what I want to do.
Define a series of strings to be called up into a function that types it onto the screen with a slight delay between each letter.
I've found some examples of people making typewriter title cards, but these are not designed to be used like functions that can be called up on the fly. For this particular project, we need the text to function like a makeshift dialog system that won't be called up until the function is called with a specific string.
Like a button with " onclick="dialogFunction(idOfStringToBeTyped) "
what I have looks like this:
var d1Example = "Hello, I am example dialog";
function dialog(dialogString) {
var i;
for (i = 0; i <= dialogString.length(); i++) {
document.write( dialogString.charAt(i) );
java.lang.Thread.sleep(50);
}}
So my attempts to code the content has been... brute force-y...
EDIT: to include my attempt, should have been there in the first place, sorry about that.
This, in theory, should work, but in practice does nothing. I probably have a syntax error. but really it doesn't make sense to me why this doesn't work.
You should look into the JavaScript functions setTimeout and Math.random().
You can use Math.random() to create a floating point integer between 0 and 1.
var multipule = 5
var rand = Math.random(); // 0.5680401974599227
var randInSeconds = rand * multipule // 2.840200987299614
var waitInSeconds = Math.round(randInSeconds) // 3
Then use the the setTimeout out method to call the code that writes each character. setTimeout takes two parameters, a function and the number of seconds:
var writeCharacter = function(){
...
};
setTimeout(writeCharacter, 300);
I'll leave it to you to work out all the timing.

Use window to execute a formula instead of using eval

My code need to execute a forumla (like Math.pow(1.05, mainObj.smallObj.count)).
My path is :
var path = mainObj.smallObj.count;
as you can see.
If needed, my code can split all variable names from this path and put it in an array to have something like :
var path = ["mainObj", "smallObj", "count"];
Since I don't want to use eval (this will cause memory leaks as it will be called many times every seconds), how can I access it from window?
Tried things like window["path"] or window.path.
If it is always unclear, let me know.
Thanks in advance for any help.
EDIT: forget to tell that some config are written in JSON, so when we take the formula, it's interpreted as "Math.pow(1.05, mainObj.smallObj.count)" so as a string.
I would say there are better solutions then eval, but it depends how the forumla can be structured. It could be precompiled using new Function (this is also some kind of eval) but allowing it to be called multiple times without the need to recompile for each invocation. If it is done right it should perform better then an eval.
You could do something like that:
var formula = {
code : 'Math.pow(1.05, mainObj.smallObj.count)',
params : ['mainObj']
}
var params = formula.params.slice(0);
params.push('return '+formula.code);
var compiledFormula = Function.apply(window, params);
//now the formula can be called multiple times
var result = compiledFormula({
smallObj: {
count: 2
}
});
You can get the path part reconciled by recursively using the bracket notation:
window.mainObj = { smallObj: { count: 2 } };
var path = ["mainObj", "smallObj", "count"];
var parse = function (obj, parts) {
var part = parts.splice(0, 1);
if (part.length === 0) return obj;
obj = obj[part[0]];
return parse(obj, parts);
};
var value = parse(window, path);
alert(value);
Basically, parse just pulls the first element off the array, uses the bracket notation to get that object, then runs it again with the newly shortened array. Once it's done, it just returns whatever the result of the last run is.
That answers the bulk of your question regarding paths. If you're trying to interpret the rest of the string, #t.niese's answer is as good as any other. The real problem is that you're trusting code from an external source to run in the context of your app, which can be a security risk.

Is there another option for jquery opacity?

I have a series of sliders that control the items / links on my site. http://wp11004271.server-he.de/alloytoy4.0/. At the moment there is only two options for these links, available (dark background) and unavailable (light background). I would like to add some in-between variables for links that are available in another capacity.
var filter = {};
var unmarkItem = function (alloy) {
var domalloy = $('#alloy_' + alloy);
domalloy.css('opacity', 1);
// alloys[alloy].marked = false;
};
var markItem = function (alloy) {
var domalloy = $('#alloy_' + alloy);
domalloy.css('opacity', 0.2);
// alloys[alloy].marked = true;
};
Iam only familiar with true or false but want to add other options.
Any thoughts on what to add?
You are currently using marked as a Boolean, which means, that it can only be two values assigned to: true or false.
If you want more options, I would recommend to use marked as an Integer, means a number without any decimal places (guess thats the right word for it, if not, correct me) so without a comma.
Create variables called for example MODE_DISABLED, MODE_INACTIVE, MODE_ACTIVE, etc. and assign number values to them, like var MODE_DISABLED = 1; or something like that.
Then you can set the modes like
alloys[alloy].marked = MODE_INACTIVE;
and dont have to keep in mind whats the value for which mode.
Your function markItem should get a second parameter for the value.

How to retrieve a conditionally set variable from inside a function?

What can I do to retrieve a conditional variable from inside a function in the webpage being parsed by greasemonkey?
Something like this:
var myglobal = 5;
function myfunc() {
myglobal = myglobal -1;
if (myglobal == -1) {
var this1 = 'Test';
document.getElementById("mybutton").href = this1;
}
}
In this case I would like to read what is in 'this1', either directly or modifying 'myglobal', calling 'myfunc' and somehow getting the value of href from 'mybutton'... any ideas?
You usually can't get a variable value from outside a scope like that, but you may not have to in this case.
"myfunc is a counter, and I want to skip it, otherwise mybutton.href won't be set yet."
Based on the sample code, you might be able to cheat that timer just by using:
unsafeWindow.myglobal = 0;
(In fact, I use this exact technique on one very misguided training site.)
To answer the stated question further, you cannot get dynamic values from within such a scope but the initial state may be enough, as it appears to be for this question.
So you could get myfunc()s code and parse it with regex to obtain the desired value:
var theFunc = unsafeWindow.myfunc.toString ();
var desiredHref = theFunc.match (/var\s+this1\s*=\s*["']([^"']+)["']/);
if (desiredHref.length > 1) {
// Found!
desiredHref = desiredHref[1];
}

JavaScript & string length: why is this simple function slow as hell?

i'm implementing a charcounter in the UI, so a user can see how many characters are left for input.
To count, i use this simple function:
function typerCount(source, layerID)
{
outPanel = GetElementByID(layerID);
outPanel.innerHTML = source.value.length.toString();
}
source contains the field which values we want to meassure
layerID contains the element ID of the object we want to put the result in (a span or div)
outPanel is just a temporary var
If i activate this function, while typing the machine really slows down and i can see that FF is using one core at 100%. you can't write fluently because it hangs after each block of few letters.
The problem, it seems, may be the value.length() function call in the second line?
Regards
I can't tell you why it's that slow, there's just not enough code in your example to determine that. If you want to count characters in a textarea and limit input to n characters, check this jsfiddle. It's fast enough to type without obstruction.
It could be having problems with outPanel. Every time you call that function, it will look up that DOM node. If you are targeting the same DOM node, that's very expensive for the browser if it's doing that every single time you type a character.
Also, this is too verbose:
source.value.length.toString();
This is sufficient:
source.value.length;
JavaScript is dynamic. It doesn't need the conversion to a string.
I doubt your problem is with the use of innerHTML or getElementById().
I would try to isolate the problem by removing parts of the function and seeing how the cpu is used. For instance, try it all these ways:
var len;
function typerCount(source, layerID)
{
len = source.value.length;
}
function typerCount(source, layerID)
{
len = source.value.length.toString();
}
function typerCount(source, layerID)
{
outPanel = GetElementByID(layerID);
outPanel.innerHTML = "test";
}
As artyom.stv mentioned in the comments, cache the result of your GetElementByID call. Also, as a side note, what is GetElementByID doing? Is it doing anything else other than calling document.getElementById?
How would you cache this you say?
var outPanelsById = {};
function getOutPanelById(id) {
var panel = outPanelsById[id];
if (!panel) {
panel = document.getElementById(id);
outPanelsById[id] = panel;
}
return panel;
};
function typerCount(source, layerId) {
var panel = getOutPanelById(layerId);
panel.innerHTML = source.value.length.toString();
};
I'm thinking there has to be something else going on though, as even getElementById calls are extremely fast in FF.
Also, what is "source"? Is it a DOMElement? Or is it something else?

Categories

Resources