Different return value console/javascript with jquery - javascript

I'm new to javascript/jquery/html, and I have to develop a little simulator with html and javascript.
I have an array with stored html id and a function that should update input based on the passed state.
The code is something like this:
var dev_array = [["#8_1", "#8_2"], ["#8_3", "#8_4"], ["#8_5", "#8_6"], ["#8_7", "#8_8"]];
function send_dev_state_ctrl(state){
dev_array.forEach(function(entry){
for (i = 0; i < entry.length; ++i) {
console.log(entry[i]);
var input =$(entry[i]);
console.log(input);
input.value =value_hash_dev[i];
handle_ctrl_send(input);
}
});
}
The console show:
#8_1
[input#8_1, context: document, selector: "#8_1", jquery: "1.10.1", constructor: function, init: function…]
...
If I digit $("#8_1") in console, I have the following output:
[<input type=​"hidden" id=​"8_1" name=​"8:​1" value=​"1">​]
What should I do to have the same return value in javascript?

I don't know why but doing:
var input =$(entry[i])[0];
It returns the same value of console.
I don't like it, but it works.

You are not $'ing up your console.log you are just spitting out the array value.
Change this:
console.log(entry[i]);
To this:
console.log($(entry[i]));
And you will get the same result for both.
---- EDIT ----
My bad i misread the question, so you are correct doing
var input =$(entry[i])[0];
Will work, this is because $(entry[i]) is an object and the first value in that object is the DOM element which is accessed by doing $(entry[i])[0];.
Another method would be do to this:
var input =$(entry[i]).get(0);
Which pretty much does the same thing.
Unfortunately there is not much other way of doing it.

Related

Using parent() in a for loop

I am creating a chrome extension that blocks all porn results on all torrent search engine sites.
So I am trying to retrieve the name of the torrents and check them against the array of strings containing blocked (adult/porn) words that I created. If it matches the array word then it should set the display of the parent element to none. But parent() from jQuery doesn't seem to work around this in a for loop. This is the code that I am using.
// 'blockedWords' is the array.
// '$("dl dt")' contains the words that I am checking against strings from
// the array 'blockedWords'.
for (var i = 0; i < $("dl dt").length; i++) {
for (var j = 0; j < blockedWords.length; j++) {
if($("dl dt")[i].innerText.indexOf(blockedWords[j]) > -1){
$(this).parent().style.display= "none"; // 1st Method or
$("dl dt")[i].parent().style.display= "none"; // 2nd Method
}
}
}
// 1st Method shows the error 'Cannot set property 'display' of undefined'
// 2nd Method shows the error '$(...)[i].parent is not a function'
// '$("dl dt")[i].parent().style.display' doesn't work but
// '$("dl dt").parent().style.display' doesn't work either
// '$("dl dt")[i].style.display' works perfectly without parent().
I have also tried 'parents()'.
Any help will be appreciated :).
As a newbie, I am also open to any other suggestions or recommendations.
And I would be really grateful if you could explain your code as well :)
And by the way, can you believe there are more than 500 porn companies out there :o :P :D
Since you have jQuery, you can avoid using nested for-loops using jQuery's filter() and JavaScript reduce(s,v):
// Filter function removes elements that return a false/falsey value like 0
$("dl dt").filter(function() {
// Save current element's innerText so we can use it within the reduce function
var str = $(this).text();
// Return sum of reduce function
return blockedWords.reduce(function(s, v) {
// For each item in blockedWords array, check whether it exists in the string. Add to total number of matches.
return s + !!~str.indexOf(v);
}, 0); // 0 = intial value of reduce function (number of matches)
}).parent().hide(); // Hide elements which pass through the filter function
Demo:
var blockedWords = [
'shit', 'fuck', 'sex'
];
$("dl dt").filter(function() {
var str = $(this).text();
return blockedWords.reduce(function(s, v) {
return s + !!~str.indexOf(v);
}, 0);
}).parent().hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<dl><dt>this is shit</dt></dl>
<dl><dt>this is okay</dt></dl>
<dl><dt>fuck this</dt></dl>
<dl><dt>no problem</dt></dl>
<dl><dt>sex videos</dt></dl>
EDIT: I apologize for the earlier answer if you saw it, as it was incomplete. I have also added a snippet for demonstration purposes. For further explanation of the reduce algorithm, check this answer out (basically it converts the value of indexOf to either a 0 or 1, because indexOf returns -1 if not found, or another 0-indexed integer of the position if found).
JQuery's parent function returns a JQuery object with the parent element inside of it. If you want to access the element from this object you need to retrieve the element from the object using the bracket notation.
If you were to provide some HTML I would be able to test this and make sure it works, but here is some code that could get you pointed in the right direction to use mostly JQuery instead of relying on for loops with JavaScript.
JQuery Rewrite
$("dl dt").each(function(index, element){
if($.inArray(blockedWords,$(element).text()) > -1) {
$(this).parent().css("display", "block");
$(element).parent().css("display", "block");
}
})
The Answer To Your Specific Question
Change this:
$(this).parent().style.display= "none"; // 1st Method or
$("dl dt")[i].parent().style.display= "none"; // 2nd Method
to this:
$(this).parent()[0].style.display= "none"; // 1st Method or
$($("dl dt")[i]).parent()[0].style.display= "none"; // 2nd Method
optionally, you can instead use JQuery's css function like this:
$(this).parent().css("display", "none"); // 1st Method or
$($("dl dt")[i]).parent().css("display","none"); // 2nd Method

About jquery storing local variable when writing plugin

Hi I am a newbie of using jQuery for writing plugin and currently facing a case on local variable handling,
and here is some code for all reference
<div class="apple"></div>
<div class="apple"></div>
<script>
var apple = [1,3];
$(function(){
$.fn.Hello = function(){
return this.each(function(){
var apple = 0;
$.fn.extend({
setApples:function(num_of_apples){
apple = num_of_apples
},
getApples:function(){
return apple;
}
});
});
}
var i = 0;
var $apples = $('.apple').Hello();
$apples.each(function(){
console.log(apple[i]);
$(this).setApples(apple[i]);
i++;
});
var j = 0;
$('.apple').each(function(){
console.log("Apple "+j+":"+$(this).getApples());
j++;
});
});
</script>
I would like the result be
Apple 0:1
Apple 1:3
But the last setting will always overwrite the last result.
Actual Results:
Apple 0:3
Apple 1:3
I try to change the variable from apple to this.apple, but it will return me undefined result. May I know what is the wrong part in my code?
I try to go to search from google and there is another alternative by using $(this).data('apple',value)for set and $(this).data('apple') for getting the value but since I would like to have some calculation on the number of apple e.g. apple++, it will be tedious to do get and set by this method
e.g $(this).data('apple',$(this).data('apple')+1);, so would like to ask whether there is any other alternative for this case, thank you.
Even if you did this.apple, you would still get the last item from the apple array. This is because you will be then using the prototype to store the value of apple which is shared across all jQuery objects. E.g
$.fn.extend({
apples:0,
setApples:function(num_of_apples){
this.apples = num_of_apples
},
getApples:function(){
return this.apples;
}
});
If you want to store a value for each element the quick way will be to actually store it on the element but use your extension methods to grab it.
$.fn.Hello = function(){
return this.each(function(){
$.fn.extend({
setApples:function(num_of_apples){
this.data("apple", num_of_apples)
},
getApples:function(){
return parseInt(this.data("apple"));
}
});
});
}
You could add checks to make sure its a number being passed into the setApples function but for now this should work.
also as a side note you can improve your loops
var i = 0;
$.each(function(){
i++
});
You can just use
$.each(function(index){
// use index here.
}
here is the documentation for it : https://api.jquery.com/each/
Also a working example of the apples problem here : https://jsfiddle.net/y27tn5wg/

Can I set two different values to an element using getElementById?

Can't I use getElementById twice in javascript file? I want to use it twice because, I want to set a default value to the element with that particular id and then on calling a function i need to change the default value. Can I do this?
Have a look at my code:
function DefaultValue(){
var default = 10.23
var update = document.getElementById('idSpnRWA');
update.innerHTML = default;
}
function setValue(){
var set = 23.56;
var finalUpdate = document.getElementById('idSpnRWA');
finalUpdate.innerHTML = set;
}
I have given a very basic code to make you understand if this way is possible?
In short: yes, you can call getElementById as many times as you want.
Please note however, that default is a reserved word in JavaScript.
Also, you're forgetting to add ; after each line.
Try this (note I renamed the default variable, and added ; where needed.
HTML
<div id="idSpnRWA"></div>
JavaScript
function DefaultValue() {
var dflt = 10.23;
var update = document.getElementById('idSpnRWA');
update.innerHTML = dflt;
}
function setValue() {
var set = 23.56;
var finalUpdate = document.getElementById('idSpnRWA');
finalUpdate.innerHTML = set;
}
DefaultValue();
setValue();
Working Fiddle: http://jsfiddle.net/9e75vnm3/
Of course you can use document.getElementById many times.
But element with a specific id can be only once at your page.
Yes you can use getElementById as many time as you want.
Problem in your code is that you are adding inner html as 10.23% which is not allowed. '%' is consider as a modulo operator. if you want to display in html than you have to concat it as string
function DefaultValue() {
var update = document.getElementById('idSpnRWA');
update.innerHTML = 10.23 + '%';
}
function setValue() {
var finalUpdate = document.getElementById('idSpnRWA');
finalUpdate.innerHTML = 23.56 + '%';
}
DefaultValue();
<div id='idSpnRWA'></div>
You cannot have the same HTML id attribute more than once on a page, but you can get anything as many times as you want, as long as it's not undefined. Of course, this means you can call document.getElementById('idSpnRWA') as many times as you want. You'll want to put percentages in quotes when assigning to .innerHTML, as % is the modulo operator. Better yet, use HTML entities. Element.innerHTML = '10.23&#037';
thank you so much for answering my question. I finally found the solution. it is,
update.value= default;
finalUpdate.value = set;
innerHTML can't be used there. If i use .value, the code is actually working fine.

Preselected ng-select value issue

I'm trying to get a preselected value within , i've tried multiple tutorials and looked for answers here but none worked.
Here's the deal ->
I load my shifts with $http.get("api/shifts"), then:
<select multiple class="form-control" ng-options="shift as shift.nom for shift in shifts" ng-model="selectedShift"></select>
And it goes to a modal window. But before this modal window opens, I can preselect a shift (to see who would be able to do it). In this case, I have
if(preselectedShift){
$http.get("api/shifts/"+preselectedShift._id).success(function(shift){
$scope.selectedShift = shift; //so it's replacing the ng-model in <select>
})
}
And all shifts appear as they should, but gives me no preselected shift. I also tried with a loop.
for (shifts.length) -> if(shift[i]._id == preselectedShift._id) ->$scope.selectedShift = shift[i]
Which gave me an error "value.forEach is not a function"
Nor ng-select="shift._id == preselectedShift._id" has worked (gives the same error).
Thank you in advance!
The problem was with "multiple" in the select tag. Multiple means that I can select multiple options and therefore the passed object is an array.
So I had to init $scope.selectedShift = [] and then, as Matthew suggested $scope.selectedShift.push($scope.shifts[x])
I think you're pretty close with your solution, it's just that forEach is not supported natively, if you use a for loop like so it should be good:
$scope.selectedShift = [];
if(preselectedShift){
$scope.selectedShift.length = 0;
$http.get("api/shifts/"+preselectedShift._id).success(function(shift){
for(var x = 0; x < $scope.shifts.length; x++){
if($scope.shifts[x]['_id'] === shift['_id']){
$scope.selectedShift.push($scope.shifts[x]);
}
}
})
}
The reason you have to do this is because in your ng-options you use shift as shift.nom ... which means that in order for it to be selected it actually has to be the same reference from the array not just something equaling it. Here's a quick example explaining (hopefully) how angular checks to see if to select something:
var myTest = { test: 4};
var myArray = [{ test: 4 }];
var myTest2 = myArray[0];
console.log(myArray[0] === myTest); //this outputs false
console.log(myArray[0] === myTest2); //this outputs true

Rewriting content of an HTML element using JavaScript

I'm new to JS, can't understand how to make this code work. I'm trying to overwrite the whole html source text.
var oldSource = document.documentElement.innerHTML;
alert(oldSource); //this works, it gets the whole html
document.write(Change(oldSource)); //doesn't work, writes undefined
function Change(source){
for (i = 0; i <= source.length; i++){
source[i] = "S"; // doesn't change the source[i]
}
}
You are changing the value of the variable oldSource, not the value of the documentElement.innerHTML.
.innerHTML just returns a string that contains the serialised content of that element. It doesn't return a reference to the content in the DOM.
Furthermore, document.write(Change(oldSource)) is saying write the return value of Change(oldSource) to the document... but your Change() function doesn't return anything, hence it is undefined.
Lastly, strings are immutable, meaning you can't change their contents after they have been created. Instead, you need to build up a new string in your function, like so:
function Change(source){
new_source = ""
for (i=0; i < source.length; i++){
new_source = new_source + "S"; //doesn't change the source[i]
}
return new_source
}
You can check all of this out in this jfiddle.
You need to return( source ); after your for loop
JavaScript strings are immutable. You can't use
source[i]="S";
to modify a string. You need to build a new string and return it.
It should be < source.length as well.
In JavaScript, this line: var oldSource = document.documentElement.innerHTML; copies the innerHTML into the oldSource variable. It does not save a reference to the innerHTML.
You are modifying the value stored in oldSource, but never applying it to the document.
In your Change function, you do not return any value - that is why you are getting an undefined. Add a 'return source;in yourChange` function to return a value.
The other problem is that you can't change the string in JavaScript. You should make a new variable for this. You can't edit source[i] - you can only retrieve the value that is there.
You need to return the new source string like below;
var oldSource = document.documentElement.innerHTML;
alert(oldSource); //this works, it gets the whole html
document.write(Change(oldSource)); //doesn't work, writes undefined
function Change(source){
for (i=0; i<=source.length; i++){
source[i]="S"
}
return source;
}
your function must return something, not just change
you cannot change strings this way, use .replace() method instead
if you specify what you really need to do, our help could be more effective
EDIT As far as I didn't find correct working code here, I want to suggest my one
function Change(source){
var str = source.split("");
for (var i=0; i<source.length; i++){
str[i] = "S";
}
return str.join("");
}
Maybe it's not the fastest way (though, why not) but it lets you to operate with indexes as you tried in your question.
working fiddle for Lego Stormtroopr
EDIT2 and this example shows how to do it in one line inside the loop (without creating extra variables)
for (var i=0; i<source.length; i++){
source = source.replace(new RegExp(source[i]), "S");
}

Categories