I am working with a page that has multiple divs that toggle. This function works. A search function was added and this works too.
The problem with the page as it exists currently: The search bar was placed on the "default" div and the results load below the bar into another div that is invisible when empty. The results div is inside this first default div. If you toggle to another div, you lose the default div and can't get back to it.
For this reason, I moved the search bar to the left navigation where the other toggle links are situated. I also moved the search results div out of the default div to "stand on its own."
What I am trying to do: Make the search button show the div with the results as well as find the results. Basically, to integrate the search function into the array/toggle function. The search function is in one .js file and the toggle function is in a different .js file.
I keep thinking there must be a way to get "onclick" to call from both .js files so that I don't have to do a bunch of extra work combining the two functions that already exist and work separately. I am a Javascript newbie learning by examples and haven't been able to figure this out. I have never seen a working example of this and my searches haven't produced one.
I would be very grateful for any help. Hope I explained the problem adequately.
Edit: Here is the code I already have for the toggle function.
var ids=new Array('a','b','c',[and so on--search results not added here yet]);
function switchid(id_array){
hideallids();
for( var i=0, limit=id_array.length; i < limit; ++i)
showdiv(id_array[i]);
}
function hideallids(){
for (var i=0;i<ids.length;i++){
hidediv(ids[i]);
}
}
function hidediv(id) {
//safe function to hide an element with a specified id
if (document.getElementById) { // DOM3 = IE5, NS6
document.getElementById(id).style.display = 'none';
}
else {
if (document.layers) { // Netscape 4
document.id.display = 'none';
}
else { // IE 4
document.all.id.style.display = 'none';
}
}
}
function showdiv(id) {//safe function to show an element with a specified id
if (document.getElementById) { // DOM3 = IE5, NS6
document.getElementById(id).style.display = 'block';
}
else {
if (document.layers) { // Netscape 4
document.id.display = 'block';
}
else { // IE 4
document.all.id.style.display = 'block';
}
}
}
function initialize(){
var t = gup("target");
if( t )
{
switchid([t]);
}
}
function gup( name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null ){
return "";
} else {
return results[1];
}
}
Thanks in advance!
When your toggle function code is loaded, the functions are declared in the Global scope. When you search functions are loaded, they are also in the Global scope. Since they are in the same scope, even though it's a different file, the toggle functions can be used by your search function, if you include the file with the search function after the file with the toggle function.
TL;DR
function search(...) {
// do your search stuff
// when you get a result ID, toggle it from here
hideallids();
showdiv(id);
}
I seriously recommend you use meaningful names, objects as namespaces to organize your code, and CamelCase or underscores to mark word boundaries in identifiers. For example:
window.ZESearch = {
'initialize' : function() { ... },
'search': function() {
// Find the node with the desired result
ZESearch.showResult(id);
},
'hideAllResults': function() { ... },
'hideResult' : function(id) { ... },
'showResult' : function(id) { ... },
...
};
ZESearch.initialize();
Since you're just learning, I've avoided the complexity of the this keyword, presented a simple way to create an object to keep your code organized but added your object to window so you can get it from anywhere in your code.
Related
So I've got this code in my page: a very simple but working script to translate it to several languages.
// preparing language file
var aLangKeys=new Array();
aLangKeys['en']=new Array();
aLangKeys['es']=new Array();
aLangKeys['fr']=new Array();
aLangKeys['cn']=new Array();
aLangKeys['en']['language']='english';
aLangKeys['es']['language']='español';
aLangKeys['fr']['language']='français';
aLangKeys['cn']['language']='中文';
aLangKeys['en']['buy']='buy';
aLangKeys['es']['buy']='comprar';
aLangKeys['fr']['buy']='acheter';
aLangKeys['cn']['buy']='买';
$(document).ready(function() {
// onclick behavior
$('.language').click(function() {
var lang = $(this).attr('id'); // obtain language id
if ($(this).attr('id') == 'es') {
$('.language').attr('id', 'fr');
}
else if ($(this).attr('id') == 'fr') {
$('.language').attr('id', 'cn');
}
else if ($(this).attr('id') == 'cn') {
$('.language').attr('id', 'en');
}
else if ($(this).attr('id') == 'en') {
$('.language').attr('id', 'es');
}
// translate all translatable elements
$('.translate').each(function(i){
$(this).html(aLangKeys[lang][ $(this).attr('key') ]);
});
} );
});
// HERE'S WHERE MY BRAIN STARTS MALFUNCTIONING
if ((window.location.pathname).split('/')[1] == 'es') {
// <-- EXECUTE FUNCTION ABOVE TO TRANSLATE TO SPANISH BASED ON PATHNAME
}
else if ((window.location.pathname).split('/')[1] == 'fr') {
// <-- EXECUTE FUNCTION ABOVE TO TRANSLATE TO FRENCH BASED ON PATHNAME
}
else {
}
So it basically translates (changes the value of certain elements on the page) when clicking a button. Every time you click on it, changes to the next language. That works fine.
THE PROBLEM is, I want it 'automatically' changed to a certain language if the user is visiting from a certain link:
Example:
www.mysite.com (nothing happens because nothing is on the pathname)
www.mysite.com/es/ ('automatically changes values to spanish')
www.mysite.com/fr/ ('automatically changes values to french')
I tried 'faking' the button click with javascript but didnt work.
Also tried 'naming' the translating function and 'call/run' it.
I know it's easier to do and I'm making it complicated but I'm such a noob.
Please, help. Or just a hint. Thanks in advance and sorry for my English.
Based on code above a couple thoughts:
1) lets change aLangKeys to an object with each key being another object.
i.e.
var aLangKeys={};
aLangKeys['en']={}; // Thats a named key/prop so we want an object here
...
aLangKeys['en']['language']='english'; // ditto the above comment
2) we probably want to move the logic that checks for locality inside the ready function.
I.e.
$(document).ready(function() {
// onclick behavior
$('.language').click(function() {
...
});
// we want access to the DOM *and* maybe certain functions that do stuff. So its gotta be in here...
if ((window.location.pathname).split('/')[1] == 'es') {
// <-- EXECUTE FUNCTION ABOVE TO TRANSLATE TO SPANISH BASED ON PATHNAME
}
else if ((window.location.pathname).split('/')[1] == 'fr') {
// <-- EXECUTE FUNCTION ABOVE TO TRANSLATE TO FRENCH BASED ON PATHNAME
}
}); // end of ready function
Couple reasons:
a) we want to change the page content based on info like pathname/locality. So we want to know the page is loaded first.
b) perhaps we will want to make a function that does language processing/changing and call that from multiple places. We want that function in scope of our locality checking logic. If we define that inside the ready function scope, we will need any logic that calls that function also inside the same scope
This question already has answers here:
How can I be notified when an element is added to the page?
(8 answers)
Closed 6 years ago.
I am trying to make a bot that sends virtual currency over to another user. I have the bot search through a database for users. Before searching, the inner html of a division has no elements at all. After searching, it is then filled with several user links.
Because it takes a short while for results to appear, I need Javascript to wait for at least one anchor tag to exist. How can I do this?
There are many, many better ways to do this, all of which stem from actually checking when the AJAX data populates the element itself, but the following will work:
var t = setInterval(function () {
if ($("element").children().length > 0) {
clearInterval(t);
// do stuff
}
}, 50);
Using setTimeout() to delay the code a few seconds is risky, since on older browser/machines it may take longer than expected.
Use promise() instead, You can find documentation https://api.jquery.com/promise/ .
Using onload event, You can use onload with tag a.
EX: http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_img_onload
I'm guessing this is an AJAX call.
You could use AJAX callback to check if you got any results from the server.
Something like this:
var tags_available = false;
$.ajax({
... the ajax stuff;
}).done(function(data){ // The callback
if(data || $('#tags_element').lenght != 0){
tags_available = true;
}else{
tags_available = false;
}
})
Then:
if(tags_available){
console.log("Tags available")
}
If I've understood you correctly you need to check if dom element have been updated/populated with new elements. There are a few ways you can achieve that:
1.) Using window.setTimeout function
function checkForChanges() {
var observeThis = document.getElementById('observethis');
if (observeThis.hasChildNodes()) {
alert('yes');
return;
/*this is gonna execute only once */
}
window.setTimeout(function() {
checkForChanges();
}, 25);
}
checkForChanges();
/* this part is only relevant for demonstration.
It shows what happens when dom element gets new child */
(function() {
var observeThis = document.getElementById('observethis');
var button = document.getElementById('button-append');
button.addEventListener('click', function() {
var anchorElement = document.createElement('a');
anchorElement.href = "http://example.com";
anchorElement.target = "_blank";
anchorElement.innerHTML = "Link";
observeThis.appendChild(anchorElement);
}, false);
})();
<div id="observethis"></div>
<button id="button-append">append anchor</button>
2.) MutationObserver class
this is modern approach (I would also say recommended one).
function checkForChanges() {
var observeThis = document.getElementById('observethis');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList') {
alert("insert your own code");
}
});
});
var config = {
attributes: true,
childList: true,
characterData: true
};
observer.observe(observeThis, config);
//observer.disconnect();
//use observer.disconnect to end observations
}
checkForChanges();
/* this part is only relevant for demonstration.
It shows what happens when dom element gets new child */
(function() {
var observeThis = document.getElementById('observethis');
var button = document.getElementById('button-append');
button.addEventListener('click', function() {
var anchorElement = document.createElement('a');
anchorElement.href = "http://example.com";
anchorElement.target = "_blank";
anchorElement.innerHTML = "Link";
observeThis.appendChild(anchorElement);
}, false);
})();
<div id="observethis"></div>
<button id="button-append">Append Child</button>
Read more about MutationObserver here
3.) If you are just waiting to get a response from ajax callback and don't actually need to observe changes in dom then just use XMLHttpRequest. Or even better. Use new javascript fetch API (you are gonna need polyfill to ensure it works in most browsers)
Having issue with - what I supposed to be - basics scope fundamentals.
I am using Javascript with Require JS structure, here are where the issue occurs:
function GameManager() {
//This is the constructor of gamemanager.js file
this.body = $('body');
this.game = $('#game');
}
GameManager.prototype.createGame = function() {
//Code
//this line works
this.body.append(//Some HTML);
}
GameManager.prototype.showGame = function() {
//Code
//this line does not work wtf
this.game.removeClass("display-none");
//and this one does work.
$("#game").removeClass("display-none");
}
I am using this.body succefully so I want to use the same way for this.game but it doesnt work. I can manage to make it work by using directly $("#game") but it's making jquery running through the DOM everytime so not really optimized...
I certainly am missing some basics points here, can someone explain ?
Thanks
This is working for me. I can remove display-none class from div without a problem. It wont display however. You need to change css. this.body.css("display","block"); for example.
window.onload = function() {
function GameManager() {
//This is the constructor of gamemanager.js file
this.body = $('body');
this.game = $('#game');
}
GameManager.prototype.createGame = function() {
//Code
//this line works
this.body.append();
}
GameManager.prototype.showGame = function() {
//Code
this.body.css("display", "block");
//this line does not work wtf
this.game.removeClass("display-none");
//and this one does work.
//$("#game").removeClass("display-none");
}
var myGame = new GameManager();
myGame.showGame();
}
I am building a django site and have implemented the redips.drag library in one of my pages to allow dragging of table rows. I want a very simple functionality in my code- add a listener, so when the row is dropped, it send the row data to the server. jQuery-speaking, something like this:
$(function() {
$(someDomElement).on('DropEvent', function() {
// send data to server
};
});
The problem though, is that redips.drag is not a jQuery plugin but a javascript one, so my knowledge is a little (more than a little) lacking. I can probably find some other library, but it's performing really well and I prefer understanding how to work with it than look for a different one.
I can probably handle the "sending the data to the server" part by myself, what I can't understand at all is how to "catch" the drop event, what part of the dom do I listen to? I tried adding monitorEvents to different selectors but failed completely.
I also tried to manipulate the script.js file (the one that initializes the row handling), but also failed. here's the one I'm using (example 20 in the redips package):
"use strict";
// define redips object container
var redips = {};
redips.init = function () {
// reference to the REDIPS.drag library and message line
var rd = REDIPS.drag,
msg = document.getElementById('msg');
// initialization
rd.init();
//
// ... more irrelevent code ...
//
// row event handlers
//
// row clicked (display message and set hover color for "row" mode)
rd.event.rowClicked = function () {
msg.innerHTML = 'Clicked';
};
// row row_dropped
rd.event.rowDropped = function () {
msg.innerHTML = 'Dropped';
};
// and so on...
};
// function sets drop_option parameter defined at the top
redips.setRowMode = function (radioButton) {
REDIPS.drag.rowDropMode = radioButton.value;
};
// add onload event listener
if (window.addEventListener) {
window.addEventListener('load', redips.init, false);
}
else if (window.attachEvent) {
window.attachEvent('onload', redips.init);
}
Now I tried adding a console.log('hello') to the rd.event.rowDropped function (right above the msg.innerHTML line), but that doesn't work, I drop the row and nothing shows in the log. Doing a console.log outside the init function works so I know the script can pass stuff to the console.
Please, can anyone help me? I'm at a complete loss...
I know this may be a little lateto answer your question but I found the answer. You need to use the event dropped and the attribute rd.obj (REDIPS.drag.obj) to get the id use it with simple javascript like getAttribute('id')
redips.init = function () {
// reference to the REDIPS.drag library and message line
var rd = REDIPS.drag,
msg = document.getElementById('msg');
// initialization
rd.init();
// row clicked (display message and set hover color for "row" mode)
rd.event.clicked = function () {
msg.innerHTML = 'Clicked' + rd.obj.getAttribute('id');
};
// row row_dropped
rd.event.dropped = function () {
msg.innerHTML = 'Dropped' + rd.obj.getAttribute('id');
};
};
Please go here to see an iframe based web app.
Click on the map of Australia, choose a city, then buy some tickets.
Now you will see the cart form located on the lower right corner.
The problem is in IE8, I cannot delete checked rows from the table;
whereas in other browsers such as FireFox3.6, Opera10, Safari4 and Chrome4, this
action is all right.
Below is the related javascript. It doesn't use jQuery, as part of the requirement
is no framework allowed! And iframes are the my best bet, ajax will simply kill me under this restriction.
/* cartForm.js */
function toDeleteRoutes() //this function is executed before form is to be submitted.
{
if(document.getElementsByClassName('delete_box').length > 0) //there're rows to delete
{
document.getElementById('cartForm').action ="./deleteRoutes.php";
document.getElementById('cartForm').target ="section4";
return true; //this enables the form to be submitted as usual.
}
else return false; //there is no more row in table to delete!
}
function toSendEmail() //this function is executed before form is to be submitted.
{
document.getElementById('cartForm').action ="./sendEmail.php";
document.getElementById('cartForm').target ="section3";
document.getElementById('delete_btn').disabled = true; //disable delete button now
return true; //this enables the form to be submitted as usual.
}
function toCancelPurchase()
{
document.getElementById('cartForm').action ="./cancelPurchase.php";
document.getElementById('cartForm').target ="section4";
return true; //this enables the form to be submitted as usual.
}
I don't know which part is wrong, or this is just because IE8 screws all?
You are using the document.getElementsByClassName method, and it is not available on IE.
You should include a custom function to have this functionality.
Personally I like a slightly modified version of the Dustin Diaz implementation:
function getElementsByClassName(node,classname) {
if (node.getElementsByClassName) { // use native implementation if available!
return node.getElementsByClassName(classname);
} else {
return (function getElementsByClass(searchClass,node) {
if ( node == null )
node = document;
var classElements = [],
els = node.getElementsByTagName("*"),
elsLen = els.length,
pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"), i, j;
for (i = 0, j = 0; i < elsLen; i++) {
if (pattern.test(els[i].className)) {
classElements[j] = els[i];
j++;
}
}
return classElements;
})(classname, node);
}
}
Check the following article, there are plenty implementations that you can use:
getElementsByClassName Speed Comparison