Vanilla JS - hoisting a querySelected variable to Window - javascript

I've been researching and trying different solutions to this literally all day.
** EDIT: regarding duplicate post: As I wrote below, a set timeout function has been attempted and successful around the function call. Please, before you close my question, atleast ask that what you’re describing as a duplicate hasn’t already been attempted… or in this case. INCLUDED in my original post. I’m not looking for cred, I’m looking for help. **
I have a reusable function takes in 3 params:
What to wrap,
wrap in what type of element
and the id of the new wrapping element (so I can control access it later.)
Here's a codeSandbox version to help you help me! https://codesandbox.io/s/queryselector-to-globe-jbffk0?file=/index.html
Goal: I'd like to include a querySelector within the function that takes in the id to eliminate the extra step, to ensure the selector is defined after the item is created, and to keep a cleaner code-base. The problem is I keep fighting between a function that's surrounded by parens...
Var wrap = (function(params){...})(window); to potentially give global scope to the queryselector(object ref) I'm trying to create, and a standard es6 function I'm more familiar with... Var wrap = (params) => {...};
import "./styles.css";
const item = document.querySelector(".item");
var wrap = (function (toWrap, wrapper, id) {
wrapper = wrapper || document.createElement("div");
wrapper.setAttribute("id", `${id}`);
toWrap.parentNode.appendChild(wrapper);
// Non-working auto id something to
// window.id = document.querySelector(`${id}`);
return wrapper.appendChild(toWrap);
})(window);
// How can I "store the window.id" just as if it were manually written right here in global scope?
wrap(item, "div", "itemadded");
Note: the window thing I read at: http://markdalgleish.com/2011/03/self-executing-anonymous-functions/
Like I said, I can provide more working code/attempts to show I've made a ton of effort if anyone is wondering.
PS, I'll definitely mark the answer and give upvotes for help.
Thanks in advance!
If your still reading, I've tried simplifying even further, adding a timeout function to ensure that the function takes in toWrap correctly... idk what else to try... :(

Related

Pass Component Name as Argument and then attach method (not working?)

Maybe I'm not using the right terms/names for my searches but I have not been able to find anything on this topic. I would have thought this would be an easy thing to find. What I'm doing is passing a component name to a function and then trying to use the component's name by attaching a method to it. I have confirmed (via Dev Tools) that the name is correctly being passed but when I use the variable and attach the method the specific request does not work. If I 'hard-code' the exact component name to the method it works perfectly. This makes me think the (various) ways I've been trying to attach the method to the variable name is incorrect (see various attempts below). Can you offer some direction here? Thank you.
Passing to Function ...
const grid_name = "grid_GroupA";
console.log(grid_name); // Shows grid_GroupA
msg_max(newItem, grid_name);
Function (only listing relevant parts)
function msg_max(newItem, grid_target) {
console.log(grid_target); // Shows grid_GroupA
// grid_GroupA.data.add(newItem); // This works ...
// grid_target.data.add(newItem); // This does not work
// (grid_target).data.add(newItem); // This does not work
// [grid_target].data.add(newItem); // This does not work
// grid_target + '.data.add(newItem)'; // This does not work
Thank you ...
Edit ...
In my attempt to provide detail I hope I haven't confused the issue.
In essence, my question is if I can type this exact string
grid_GroupA.data.add(newItem);
and it works for my function, how can I place a variable with the exact string "grid_GroupA" in front of ".data.add(newItem);" and have it seen the same as the line of code that works? Maybe my lack of knowledge here is getting in the way but isn't the line of code that works just a string that is then used to 'find' the object? So, if that assumption is correct, how do I create that same string with the variable? If my assumption is wrong I am a willing learner so I will be all ears. Thank you.
I do not see how grid_target is an object. You are passing grid_name(which is a string) to the function, so grid_target will have no data property, because string doesn't have such a member.
P.S. snake_case is bad option for JavaScript, consider using cameCase instead

How to make javascript function can use after dot

I'm doing firebase project these days, and i got a question about something.
var citiesRef = db.collection("cities");
citiesRef.where("state", ">=", "CA").where("population", ">", 100000)
Those where() are stick together after dot and i have no idea.
How can i make function or class like that? I don't even know how to search !
I tried to make classes and unnamed functions but it doesn't work.
If i get to know about it, it'll be very useful for me. I really want to know.
Please help please
This is something akin to the Builder Pattern. The idea is to return the object after appending a condition.
Example code (language agnostic):
def where(condition){
self.appendCondition(condition)
return self // Important part
}
The return self enables to chain methods on the same object. Each one returns itself with the new condition appended.

Strange javascript behaviour - error unless 'classes' are defined in correct order

I have a very strange problem with javascript and easel js.
I am using the easel.js library and am already fairly far into the construction of a project using it.
I am attempting to have a 'class' (I know they aren't technically classes in javascript but I will use this terminology for lack of a better word) inherit the Shape class from easel js, and then have another class inherit that. So it would be something like this:
easeljs.Shape --> MenuButton --> BuildingButton
The code I am using looks like this:
BuildingButton.prototype = Object.create(MenuButton.prototype);
BuildingButton.prototype.constructor = BuildingButton;
function BuildingButton(){
MenuButton.call(this);
}
MenuButton.prototype = Object.create(createjs.Shape.prototype);
MenuButton.prototype.constructor = MenuButton;
function MenuButton(){
createjs.Shape.call(this);
}
The problem is that I get the following error with this code:
Uncaught TypeError: undefined is not a function
easeljs-0.7.1.combined.js:8439
(line 8439 is pointing to the initialize() function in the Shape() constructor).
now here's the strange thing. If I change the order of the definitions so that the sub class is defined second and not first, it works fine!
MenuButton.prototype = Object.create(createjs.Shape.prototype);
MenuButton.prototype.constructor = MenuButton;
function MenuButton(){
createjs.Shape.call(this);
}
BuildingButton.prototype = Object.create(MenuButton.prototype);
BuildingButton.prototype.constructor = BuildingButton;
function BuildingButton(){
MenuButton.call(this);
}
This is very confusing as I can't seem to figure out why on earth this is happening. I could just make sure I define them in the correct order and leave it be, but I have all my 'classes' in different source files which are then strung together by grunt, which does so alphabetically.
Also, I feel like I may have a big gap in my knowledge of javascript (or maybe easel.js I'm not sure what exactly is causing this behaviour).
Thanks in advance for your help and I hope the question makes sense!
MenuButton.prototype = Object.create(createjs.Shape.prototype);
…
BuildingButton.prototype = Object.create(MenuButton.prototype);
These two statements have a clear dependency and need to be executed in the correct order (for the function declarations the order is irrelevant if placed in the same scope/file, but if in different files they need to be loaded in the correct order obviously).
I have all my 'classes' in different source files which are then strung together by grunt, which does so alphabetically
That's not a good idea. You should use some build tool/script that allows the declaration of dependencies.
Read this to clear things out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
In first example you try to inherit from nothing, since MenuButton.prototype is not yet defined. To make it work just add MenuButton.prototype = new createjs.Shape.prototype(instead of Object.create() wich shouldn't be used anymore) to instantiate it first before you can you use it. Your first code is like you are willing to eat a banana before having one.

Prototype injection, google maps api

I need to catch the event of getting back suggestions for google maps autocomplete. I know it is undocumented, but doing some research I found that it could be down via some prototype hacking.
<input type='text' id='myInput'>
<script src="http://maps.google.com/maps/api/js?libraries=places&sensor=false&language=en-EN"></script>
<script>
function catcher(key) { console.log(key); }
function MyProto() {}
MyProto.prototype = new google.maps.MVCObject();
MyProto.prototype.changed = catcher;
var gAuto = new google.maps.places.Autocomplete(
document.getElementById('myInput'), ['geocode']);
// one of two should be commented
//gAuto.__proto__.__proto__.changed = catcher; // every key, including 'predictions'
gAuto.__proto__.__proto__ = MyProto.prototype; // only 'types', '0', and 'place' when selected
</script>
JSFiddle link: http://jsfiddle.net/agentcooper/hRyTF/ (check the console)
Check the last two lines. When setting 'changed' function directly on MVCObject prototype (first one, commented), everything works great and I can catch key 'predictions' in the 'catcher' function. The problem is that catcher needs to be different if, for example, I need to have two instances of autocomplete on my page. So when I'm trying to inject custom object in autocomplete's prototype chain (last line) everything fails. Is there any way to solve this?
EDIT: working version, thanks to Sajid :-)
UPDATE: Completed the code, maybe it will be helpful to anyone
In the second line, you are replacing the entire prototype of the MVC object with an instance of the MVC object, and depending on how the thing is initialized, this will likely not work at all. The first like replaces one function, though in the process it completely breaks that function since you don't call its superclass version, so you are not extending, you are really clobbering. To not clobber, you need to do:
(function() {
var oldChanged = gAuto.__proto__.__proto__.changed;
function catcher(key) {
// call old version, and make sure to maintain this reference correctly
oldChanged.call(this, key);
// do your stuff here
}
gAuto.__proto__.__proto__.changed = catcher;
})();
One simple solution is that each object has an idea of this mentioned above. So changed has a reference to this, which will refer to the object being used as the caller's target (except in specific situations that are a bit out of scope here). But basically:
var x = new MVCObject();
x.changed('hi') // this === x
So if your two versions need to do different things, you can check which this the changed method was called from and react appropriately.

How to set a javascript variable or reuse one from another function

I have a problem going on here and without going into a lot of detail and confusing everyone, let me just ask the simple question.
Here are two functions. I need to use the "id" variable in the SubmitForm() function as well. Can someone please tell me how to do this? This is how new I am to js. :)
Thanks for the help.
AC.chooseFunc = function(id,label)
{
document.qSearch.action = ".index.php?dc=2&id="+ id;
//document.qSearch.action = "index.php?dc=2";
document.qSearch.submit();
}
*** This one fails.
function SubmitForm(id)
{
document.qSearch.action = "index.php?dc=2&id="+ id;
document.qSearch.submit()
}
What I need is the "id" var appended to the query string in the SubmitForm Function. Can someone tell me how to do this please? Thanks for the help!
Can this not be done??
First, as a disclaimer, I think we would all be able to give you better answers if you post an example page demonstrating how the document is put together.
Here's one way you can make it work. At or near the top of your script (or <script> tag) declare a variable:
var storedId;
Then, at the top of AC.chooseFunc, copy the value of id to storedId:
AC.chooseFunc = function(id,label)
{
storedId = id;
...
Finally, remove id from SubmitForm's parameters and use storedId instead:
function SubmitForm()
{
document.qSearch.action = "index.php?dc=2&id="+ storedId;
document.qSearch.submit();
}
i dont know if you would want to do this, but you could make the variable global in other words declare it outside of both functions.
Could you not just use a hidden input and have PHP add it to the query string?
Is id null? Check the value of id...
alert(id);
The second function looks OK to me. The problem could be your passing null into it.
it's pretty clear that the two functions aren't being called in the same way.
As mentioned in another comment, alert the value to see what you're really getting in the function.
The function itself looks fine, so the only conclusion is that they are not working from the same data OR they are called in different ways.
I'd recommend posting a little more of the code in the call tree

Categories

Resources