How can i replace some "this" only outside functions? - javascript

I would like to replace some "this" in a script.
$(this).find('option').each(function() {
$(this).hide();
})
Is there a possibility to replace only the outer this, or only the "this" that are not inside a function block? My idea doesn't work ...
.replace(/([^{])\bthis\b([^}])/gm, $1replacement$2)
addendum: The first code is handled as a string, not as javascript!
I am search for a regexp to replace only the outer "this".

If I understand your issue correctly, you are wanting to refer to the $(this) variable from within your function, however that variable gets changed to the local scope of the function. So within the function, $(this) will refers to the item you are currently iterating over.
You'll want to cache the scope of the $(this) object before you enter your function.
var cached_this = $(this);
$(this).find('option').each(function() {
cached_this.hide();
})
Now you have access the value of the outer $(this) from within a different scope using the cached_this variable.

The way to distinguish "outer" from "inner" text is that for inner, the next curly bracket is a right one, which closes the block its in.
So, using a negative look ahead to exclude this within a block:
str = str.replace(/\bthis\b(?![^{]*\})/gs, replacement);
Also note the simplification of the replacement term, since the match is just the target text "this".
See a live demo of this regex working.

In that case this is an object. It's not a string that you can replace. You may assign another value, but such a replacement will not work.

If you want to replace only certain divs, simply change your jQuery selector to select those with a certain class, or child elements of a parent div, for example.

You can try to use call. Due to this function you can replace this object:
$(this).find('option').each(function() {
// here this === replacement
$(this).hide();
}.call(replacement))

If it's in a function, you can "replace" this by assigning a different variable to it when you call it.
var func = function() {
$(this).find('option').each(function() {
$(this).hide();
});
};
func.apply(annotherThis);

Related

Function parameter evaluates to undefined

When dynamically creating an element of type select, there are two problems when setting the onclick method:
It is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
This results in a final HTML tag where no onclick is shown at all.
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
However the functionality seems to be broken, as the argument always evaluates to undefined
Here a simple example of my problems:
var selectElem = document.createElement("select");
selElem.id="articleSelector_"+this.articleIndex;
console.log("the index of the article is " + this.articleIndex);
selElem.setAttribute("onclick","updateInput(this.articleIndex);");
//selElem.onclick="updateInput(this.articleIndex)"; //this does not work
The log shows the correct number. Inside the updateInput method, the argument is of value undefined instead of the number previously shown in the log.
Try attaching handlers with pure Javascript, and not with HTML, without onclick = "... (which is as bad as eval).
The this in your script refers to the calling context of the function - what is it?
You might want:
element.addEventListener('click', () => {
updateInput(this.articleIndex);
});
(arrow functions retain the this of their surrounding scope)
it is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
What that code does is it assigns the string "updateInput(this.articleIndex)" to the onclick which makes no sense and certainly not what you want.
Even if you remove the quotes:
element.onclick = updateInput(this.articleIndex);
It is still incorrect because it assigns the result of the updateInput() function to the onclick which is again not what you want.
You need to assign a function name to the onclick like this:
element.onclick = updateInput;
However, this doesn't allow you to pass a parameter as you wish. To do so, you need to use an anonymous function:
element.onclick = function() {
updateInput(this.articleIndex)
};
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
This works because it sets the attribute onclick and it is a string type, so everything is correct. It is equivalent to using the anonymous function above. The only difference is this, which in this case refers to the element itself, while in the above code it depends on the context that the code appears in. That's why in this case the argument always evaluates to undefined because the select element doesn't have an articleIndex property.
The problem is the value of the context this when that element is clicked, the context this is not available anymore at that moment.
You have two ways to solve this problem:
You can use the function addEventListener to bind the event click, and bind the function/handler with the desired context this:
The function bind binds a specific context to a function.
selElem.addEventListener('click', updateInput.bind(this));
function updateInput() {
console.log(this.articleIndex);
}
As you need a specific value, you can use data attributes. That way, you don't need to worry about the context this.
selElem.dataset.articleIndex = this.articleIndex;
selElem.addEventListener('click', function() {
updateInput(this.dataset.articleIndex); // Here you can get that value.
});

What is the meaning of this jQuery selection? Why we use "this" into filter()?

I use filter() in this way but it doesn't work :
$("p").filter(function(){
return $("span").length == 2;}).css("background-color", "yellow");});
If I add this alongside "span" the problem is tackled. I don't know what's the reason of being 2 element seperated with , into one $ and what meaning that it has. Actually I didn't see 2 parameter together into $ so far. Please tell me when and why I must use this in this example?
$("p").filter(function(){
return $("span", this).length == 2;}).css("background-color", "yellow");});
The second argument is the context, meaning that your selector will try to find span within the context, the this refers to the p itself in your case, so all the matched spans will be within the p context.
It seems from the code that you have more than 2 spans all through the document (global context) so when you used :
$("span").length in the global context it was more than 2.
But within the context of the p, when using $("span", this) you found 2 children spans.
this refers to the last declared object. In this case, refers to $("p").

$(this) not working within if ($(".element").is()

My expected result for the code below is .csr-area-3 .csr-video with added classes csr-animate csr-zoom-in, why does $(this) not work in this situation?
if ($(".csr-area-3 .csr-video").is(":in-viewport")) {
$(this).addClass('csr-animate csr-zoom-in');
}
Because the context is the caller function / event or maybe the global window context, use the same selector again in order to add the class:
if ($(".csr-area-3 .csr-video").is(":in-viewport")) {
$(".csr-area-3 .csr-video").addClass('csr-animate csr-zoom-in');
}
Edit from comments
Use a variable to store the results of the jquery lookup:
var csrvideo = $(".csr-area-3 .csr-video");
if (csrvideo.is(":in-viewport")) {
csrvideo.addClass('csr-animate csr-zoom-in');
}
Note: using filter as #saptal's answer will assure the class to be added to the element(s) within viewport in case multiple elements exist.
You need .filter(function), to get the matched element which are in-view port and then add class to then
$(".csr-area-3 .csr-video").filter(function() {
return $(this).is(":in-viewport");
}).addClass('csr-animate csr-zoom-in');
You could also use
$(".csr-area-3 .csr-video:in-viewport").addClass('csr-animate csr-zoom-in');
If you only use
$(this).someFunction();
this refers to the window object.
You need to do
$(".csr-area-3:in-viewport").addClass('csr-animate csr-zoom-in');
$(".csr-video:in-viewport").addClass('csr-animate csr-zoom-in');
(Depends on what you actually want)

confusion over simple variable declaration jQuery "$variable" vs javascript "var"

I have this simple ghost text implementation:
HTML code:
<div id="searchPanel">
<form method="get" id="searchBox" action="somePage.php">
<input class="ghText" type="text" name="query" value="search here"/>
</form>
</div>
jQuery code:
$(document).ready(function(){
$txtField = "#searchPanel form input.ghText";
var value = $($txtField).val();
$($txtField).focus(function(){
if($(this).val() == value)
$(this).val("").removeClass("ghText");
});
$($txtField).blur(function(){
if($(this).val()==""){
$(this).val(value).addClass("ghText");
}
});
});
The example above is not going to work. When the user focuses the cursor on the search bar, the class "ghText" wont be removed for some reason.
However now if I change the "var value" (variable initialization) and "value" with
"$value" as in:
$value = $($txtField).val();
$(this).val($value).removeClass("ghText");
$(this).val($value).addClass("ghText");
everything works perfectly.
I can just go to sleep and not worried too much about it..but I am very curious why something like that can happen?
is it because of the "this" not referreing to the right object, or is it because i tried storing jQuery object in non-jQuery variable or is it about something else..can somebody point out to me what was wrong? I have always thought that "var x" is the same as "$x"..?
You seem to be confused about JavaScript variables. There is no such thing as "jQuery variables" and "non-jQuery variables". Some specific cases:
A variable declared with var is different to a variable without. "var x" is a local variable, so it will not share a value with other functions which also have a variable called "x". This is almost always a good thing, so you should almost always declare variables with "var".
The $ in jQuery is sort of special. It isn't that special; it's just that jQuery has declared a variable called "$" which does some fancy operations.
There is nothing special about variables that begin with "$". In other words, "$x" is just a variable name. It is a different variable to "x", and it isn't a "jQuery variable". It's just a JavaScript variable called "$x". (This is different from PHP, where the $ is actually a special variable syntax.)
So you can just call it "value" instead of "$value".
Possibly the fact that you removed the "var" changed things by making it into a global variable.
As for "this", yes, that is a tricky aspect of JavaScript, and might be causing your problem. The value of "this" inside the inner 'focus' and 'blur' functions is likely to be different from the value of "this" outside. I'm not sure exactly what "this" refers to in an event handler, but it will not be the same object. So what you probably want to do is assign "this" to a variable in the outer function, and then refer to that variable on the inside in place of "this".
When storing a jQuery selection in a variable, it's common practice to add a $ before the variable name like this:
var $banner = $('#banner');
It's not necessary to include the dollar sign — var banner = $('#banner') would work just as well. However, the dollar sign reminds you that the variable holds a jQuery selection and not just any value like a number or a string.
#mgiuca is entirely right about Javascript variables - the '$' that precedes them is just a naming convention that most use to identify jQuery objects. I add this because you say
because i tried storing jQuery object
in non-jQuery variable
but this is wrong. $txtField is a string that you are using to select an object. If you want to store the object itself you should do $txtField = $(#searchPanel form input.ghText) and then use it thusly $txtField.val().
Having said that your code works fine for me unaltered. I've set up a demo which works on Chrome - is this a cut down version of you code?
In to addition #mgiuca's answer here is a little more elaborate approach to your problem that also shows some of the jQuery concep:
$(document).ready(function () {
// define two helper functions
var removeDefault = function () {
if( $(this).val() == $(this).data("defaultValue") ) {
$(this).val("").removeClass("ghText");
}
};
var setDefault = function () {
if( $(this).val() == "" ) {
$(this).val( $(this).data("defaultValue") ).addClass("ghText");
}
};
// the following works on all input elements
$("#searchPanel form input.ghText").each(function () {
$(this)
.data("defaultValue", $(this).val())
.focus(removeDefault)
.blur(setDefault);
});
});
Note
the use of .data() to associate a value with a specific element.
the use of .each() to apply the same behavior to any number of elements
the use function references for .focus() and .blur() - jQuery will always set the this correctly on its own
see it working over here http://jsfiddle.net/xsXxn/
So $x is a jQuery variable after all :) ... Well, anyway, here is one instance when $ or not $ did make a big difference in my code:
...load("whatever.php", {par1: var1, par2: var2})
didn't work, at least inside the $(obj).attr() assignment, unless $var1, $var2 where used. This worked:
$(obj).attr("onClick",$("#wherever").load("whatever.php", {par1: $var1, par2: $var2})...

mootools "this" in each?

Probably misunderstanding something simple, but i can't seem to get this to work.
I want to: go trough each img element in "wrapper", and strip all html from the title attribute (with stripTags() from mootools more). I get the error:
"this.get is not a function"
here is the code:
$('wrapper').getElements('img').each(function() {
var oldAlt = this.get('title').stripTags();
this.setProperty('alt', oldAlt);
});
Thanks in advance
$('wrapper').getElements('img').each(function(el) {
var oldAlt = el.get('title').stripTags();
el.setProperty('alt', oldAlt);
});
this does not refer to the looping element -- the first argument to the .each callback function is element passed, the second is index (opposite to jquery where index is first).
The other option is to bind the this variable
$('wrapper').getElements('img').each(function() {
var oldAlt = this.get('title').stripTags();
this.setProperty('alt', oldAlt);
}).bind(this);
The extra .bind(this) basically means, in the scope inside the each function, the variable this is bound to whatever value is refers to outside. (like passing the variable into the scope). If you have need to access the normal this pointer as well, as the outside reference, you should go with an option such as #Chetan's answer

Categories