I'm having toruble with this function, it requires two clicks before the if statement is satisfied even though in the CSS the condition should be met. On the fist click, the console shows triggered but not if state on the second click it does show if state can anyone understand why the condition is not being met?
function searchShow() {
console.log('started');
document.getElementById('top_line_2a').addEventListener('click', function() {
console.log('triggered')
var searchClickIcon = document.getElementById('top_line_2a');
var searchClick = document.getElementById('top_line_3');
if(searchClick.style.height == '0em') {
console.log('if state');
//searchClick.style.display = 'block';
searchClick.style.height = '3em';
searchClickIcon.style.color = 'white';
searchClickIcon.style.textShadow = '0px 0px 7px white';
document.getElementsByClassName('search')[0].focus();
} else {
//searchClick.style.display = 'none';
searchClick.style.height = '0em';
searchClickIcon.style.color = 'rgba(255, 187, 61, 1)';
searchClickIcon.style.textShadow = '';
}
})
console.log('added');
}
When implementing ping-pong / toggle effects, try not to compare with attribute value directly. The zero height could be "0em", "0", or numeric 0. You could try normalizing the value for this one particular case:
if (parseInt(searchClick.style.height,10)==0) {
// show the container
} else {
// hide the container
}
A much more reliable way is to take advantage of the fact that every DOM element can be dynamically assigned new attributes. Since you already have a handle to the searchClick object:
if (searchClick.showing){
searchClick.showing=null;
// hide the container
} else {
searchClick.showing=true;
// show the container
}
"showing" is your own attribute. When you first click on it, the marker is not there, so it'll show the container (initially hidden). Then the showing flag is attached to it, so you can detect it in the next click. If your initial state is showing, then use a different flag to reverse the logic. This is a sure fire method to implement a toggle.
You shouldn't be using the height. Use a variable instead.
var triggered = false;
function searchShow() {
document.getElementById('top_line_2a').addEventListener('click', function() {
//Do stuff
if(!triggered) {
triggered = true;
//Do stuff
} else {
triggered = false;
//Do stuff
}
})
}
Checking for a style in an if statement isn't a good practice. If you ever change the size of your container for X reason, you'll also have to change the if/else statement to fit the change. It also make the code that much less clear to whoever will read it. Always try to avoid using hardcoded numbers when you can use something more effective.
Related
I have some javascript which looks at the body and finds words and if one is present, it outputs a div. This is useful for many things, however...
What I need to do is also look at the body and all the ALT tags for the page as well.
I found this: Use javascript to hide element based on ALT TAG only?
Which seems to change the ALT attribute, however I want to perform an action.
Here's my JS so far.
var bodytext = $('body').text();
if(bodytext.toLowerCase().indexOf('one' || 'two')==-1)
return;
var elem = $("<div>Text Here</div>");
Thank you.
P.S. I am a N00B/ relatively new at JS, I am doing this for a small project, so I am not sure where to start for this in terms of JS functions.
Updated Answer
Try this out, I commented the code to explain it a bit.
// build array of triggers
var triggers = ['trigger1','trigger2','trigger3'];
// wait for page to load
$(function() {
// show loading overlay
$('body').append('<div id="mypluginname-overlay" style="height:100%;width:100%;background-color:#FFF;"></div>');
// check page title
var $title = $('head title');
for(trigger of triggers) {
if($($title).innerHTML.toLowerCase().indexOf(trigger) >= 0) {
$($title).innerHTML = '*censored*';
}
}
// check all meta
$('meta').each(function() {
var $meta = $(this);
for(trigger of triggers) {
if($($meta).attr('name').toLowerCase().indexOf(trigger) >= 0) {
censorPage();
return; //stop script if entire page must be censored
} else if($($meta).attr('content').toLowerCase().indexOf(trigger) >= 0) {
censorPage();
return; //stop script if entire page must be censored
}
}
});
// check all img
$('img').each(function() {
var $img = $(this);
for(trigger of triggers) {
if($($img).attr('alt').toLowerCase().indexOf(trigger) >= 0) {
censor($img);
}
}
});
// check all video
$('video').each(function() {
var $video = $(this);
for(trigger of triggers) {
if($($video).attr('alt').toLowerCase().indexOf(trigger) >= 0) {
censor($video);
}
}
});
// if you want to be extra careful and check things like background image name,
// you'll have to run this code here - very inefficent
// but necessary if you want to check every single element's background image name:
for($element of $('body').children()) {
for(trigger of triggers) {
if($($element).css('background-image').toLowerCase().indexOf(trigger) >= 0) {
$($element).css('background-image','');
}
}
}
, function() { // Not sure if this is totally correct syntax, but use a callback function to determine when
// when the rest of the script has finished running
// hide overlay
$('#mypluginname-overlay').fadeOut(500);
}});
function censor($element) {
// just a basic example, you'll probably want to make this more complex to overlay it properly
$element.innerHTML = 'new content';
}
function censorPage() {
// just a basic example, you'll probably want to make this more complex to overlay it properly
$('body').innerHTML = 'new content';
}
---Original Answer---
I'm not sure exactly what you would like to do here, you should add more detail. However if you choose to use jQuery, it provides tons of useful methods including the method .attr(), which lets you get the value of any attribute of any element.
Example:
var alt = $('#my-selector').attr('alt');
if (alt == 'whatYouWant') {
alert('yay');
} else {
alert('nay');
}
You're using jQuery lib, you could select elements by attribute like:
$('[alt="one"]').each(function(el){
// do something
var x = $(el).arrt('alt');
});
If you use selector $('[alt]') you can get elements that have this attribute set, and then check the value of the element if you have a more complicated selection.
Than you have to change your return, as you could not put a div inside an ALT tag, it didn't work.
Here is about what is your expected output.
UPDATE
As you want to change all images and video in a page, the way to do this with jquery is through $.replaceWith():
$('img,video').replaceWith($('<div>Text Here</div>'));
If you need to filter the elements:
$('img,video').each(function(el){
if($(el).prop('tagName') == 'IMG' &&
$(el).attr('alt') == 'the text...') {
$(el).replaceWith($('<div>Text Here</div>'));
}
})
But I'm not an expert on Chrome Extensions, I just put this code here in jQuery, as you was using jQuery.
Of course it could be done, with much code with plain javascript and the DOM API.
Hello I want to make a Menu thats pops out of the side when I click a button. I have it all set up with the CSS but the Javascript part doesn't work.
I want to test if the width of menubarWrapper is equal to 300 then the width of the menubarWrapper needs to change to 0px and if it isn't equal to 300px than change it to 300px.
I have the following JS:
function menuBarToggle() {
var menuWrapper = document.getElementById('menuWrapper');
if menuWrapper.width == 300 {
menuWrapper.style.width = "0";
} else {
menuWrapper.style.width = "300";
}
}
I also tried in the IF statement menuWrapper.style.width but that doesn't work also
There are other answers that are just fine --
use "300px", not "300"
Surround your conditional with a parentheses.
(You'll need both, by the way.)
But I wanted to make sure that somewhere on this page, someone pointed out that this is a very brittle way of toggling. You have a magical, hardcoded integer for the size, which might break if you ever wanted to style things differently. And if you decide one day to fade out the menu, then the test won't work at all.
Might I suggest that, instead, you create two classes in CSS:
.menu-item { width: 300px; }
.menu-item.collapsed { width: 0; }
And then in javascript, you'll only have to write the following:
function menuBarToggle() {
var menuWrapper = document.getElementById('menuWrapper');
menuWrapper.classList.toggle('collapsed');
}
Not only is the intention easier to read, but this will allow you to swap out the behavior if you decide that, instead of purely narrowing the menu, you might want it to fade out, or animate it to the left, or... well... whatever can come up with.
Your script has a typo. Add '()' for an if statement.
function menuBarToggle() {
var menuWrapper = document.getElementById('menuWrapper');
if (menuWrapper.width == 300) {
menuWrapper.style.width = "0";
} else {
menuWrapper.style.width = "300";
}
}
When changing the width of an element via style.width, you have to append px to the end of the string:
function menuBarToggle() {
var menuWrapper = document.getElementById('menuWrapper');
if menuWrapper.width == 300 {
menuWrapper.style.width = "0px";
} else {
menuWrapper.style.width = "300px";
}
}
I'm still developing a genius forum for my website. I want to add some fancy javascript effects. I don't want to use jQuery for now.
My problem is the following: I have an element which appears by checking if the value of the function is true or false. With those check my article shows or hides.
My question is: Is it possible to use transitions so that my block drops down like the way transitions do?
The first js function describes the check and the next function hides or show my article when the values are not empty.
function CheckEmptyValues() {
var inputFields = document.getElementsByTagName('input');
var textFields = document.getElementsByTagName('textarea');
var postData = [inputFields, textFields];
for(var i=0; i<postData.length; i++) {
for(var j=0; j<postData[i].length; j++) {
if(postData[i][j].value !== '') {
return false;
}
}
}
return true;
}
function showPreview() {
if (CheckEmptyValues() === false) {
this.prevPost.style.display = "block";
}
else {
this.prevPost.style.display = "none";
}
}
When my emptyvalues are false the article appears and if not, it disappears. But when this happens you see only show or hide, no further effect or something.
I want to make this something like this effect: http://www.w3schools.com/css/tryit.asp?filename=trycss3_transition1
The height value should start with 0 and end with 150 height or something like that.
Does anyone have a solution how to make this look cool?
Thanks in advance.
No, you can't, display is defined as non animatable.
If you want workarounds, see CSS3 Animation and Display None.
No, display doesn't come in transition-property. But, you can try opacity and for the display:block , put it in your div:hover or only div css.
You could use opacity, and set it to 0 or 1:
this.prevPost.style.display = "block";
this.prevPost.style.opacity = 1;
I am working on homework that involves working with javascript. Part of my homework assignment is to use the event handlers onmouseout and onmouseouver. What is supposed to happen when the user hovers over a specific div element, the font size grows by 25%, and when the user mouses out of the div element, the font size goes back to normal. My question is, is it possible to incorporate both an onmouseover function and an onmouseout function into one function? Somehow that is what my teacher wants us to do. I have this started so far.
function FontSize(x)
{
x.style.fonstSize = large;
}
I'm also thinking this isnt the correct code to make the font 25% larger, but I'm not sure how to really incorporate an onmouseout in this function.
As a teacher myself, I am 99% sure that by "one function" the instructor means one general-purpose function to change the font size, not one function which uses conditional statements to work backwards and figure out whether it should be doing onmouseout or onmouseover.
Your script should contain:
function resize(elem, percent) { elem.style.fontSize = percent; }
Your HTML should contain:
<div onmouseover="resize(this, '125%')" onmouseout="resize(this, '100%')"
Text within div..
</div>
Note: Situations such as here, are exactly why JavaScript has the keyword "this"--to save us from needing to use complicated document.getElementById() statements.
You can use "%" property for controlling font-size as described here with the following code.
document.getElementById("div1").onmouseover = function() {
document.getElementById("div1").style.fontSize = "125%"
};
document.getElementById("div1").onmouseout = function() {
document.getElementById("div1").style.fontSize = "100%";
};
Here is the working jsfiddle : http://jsfiddle.net/LxhdU/
Yes you can. Call the same function on both events, and pass a parameter to indicate whether the fontsize should increase or decrease.
ChangeFontSize = function(element, shouldIncreaseFontsize)
{
var small=14;
var large = small * 1.25;
if(shouldIncreaseFontsize) {
element.style.fontSize = large + "px";
}
else {
element.style.fontSize = small + "px";
}
}
http://jsfiddle.net/TMHbW/1/
I'd do something simple like the following. The large and small values can be whatever you need them to be for the font size to work or they can be variables you've defined in prior code.
Demo: http://jsfiddle.net/lucuma/EAbYn/
function doHover(e) {
if (e.type=='mouseover') {
this.style.fontSize = "large";
} else {
this.style.fontSize = "small";
}
}
var el = document.getElementById('myelement')
el.onmouseout =doHover;
el.onmouseover=doHover;
It is possible you do not need to call both the events on the element explicitly instead extension you create will do that.Extend the Element's prototype. Jquery also does similar to this.
Ref Prototype
See Fiddle:- http://jsfiddle.net/4fs7V/
Element.prototype.hover= function( fnOver, fnOut ) {
this.onmouseover=fnOver;
this.onmouseout=fnOut || fnOver;
return this;
};
document.getElementById('test').hover(function(){
//do your mouseover stuff
},
function(){
//do your mouseout stuff
});
Update
Same can be achieved with just one function too:-
Hover me
.largeFont {
font-size:125%;
}
Element.prototype.hover = function (fnOver, fnOut) {
this.onmouseover = fnOver;
this.onmouseout = fnOut || fnOver;
return this;
};
document.getElementById('test').hover(changeMe);
function changeMe()
{
if(this.hasAttribute('class'))
{
this.removeAttribute('class');
}
else
{
this.setAttribute('class', 'largeFont');
}
}
I have been looking around and I cannot seem to figure out how to do this, although it seems like it would be very simple.(mobile development)
What I am trying to do is display a message (kind of like an alert, but not an alert, more like a dialog) while a calculation is being made. Simply like a Loading please wait. I want the message to appear and stay there while the calculation is being done and then be removed. I just cannot seem to find a proper way of doing this.
The submit button is pressed and first checks to make sure all the forms are filled out then it should show the message, it does the calculation, then hides the message.
Here is the Calculation function.
function scpdResults(form) {
//call all of the "choice" functions here
//otherwise, when the page is refreshed, the pulldown might not match the variable
//this shouldn't be a problem, but this is the defensive way to code it
choiceVoltage(form);
choiceMotorRatingVal(form);
getMotorRatingType();
getProduct();
getConnection();
getDisconnect();
getDisclaimer();
getMotorType();
//restore these fields to their default values every time submit is clicked
//this puts the results table into a known state
//it is also used in error checking in the populateResults function
document.getElementById('results').innerHTML = "Results:";
document.getElementById('fuse_cb_sel').innerHTML = "Fuse/CB 1:";
document.getElementById('fuse_cb_sel_2').innerHTML = "Fuse/CB 2:";
document.getElementById('fuse_cb_result').innerHTML = "(result1)";
document.getElementById('fuse_cb_res_2').innerHTML = "(result2)";
document.getElementById('sccr_2').innerHTML = "<b>Fault Rating:</b>";
document.getElementById('sccr_result').innerHTML = "(result)";
document.getElementById('sccr_result_2').innerHTML = "(result)";
document.getElementById('contactor_result').innerHTML = "(result)";
document.getElementById('controller_result').innerHTML = "(result)";
//Make sure something has been selected for each variable
if (product === "Choose an Option." || product === "") {
alert("You must select a value for every field. Select a Value for Product");
**************BLAH************
} else {
//valid entries, so jump to results table
document.location.href = '#results_a';
******This is where the message should start being displayed***********
document.getElementById('motor_result').innerHTML = motorRatingVal + " " + motorRatingType;
document.getElementById('voltage_res_2').innerHTML = voltage + " V";
document.getElementById('product_res_2').innerHTML = product;
document.getElementById('connection_res_2').innerHTML = connection;
document.getElementById('disconnect_res_2').innerHTML = disconnect;
if (BLAH) {
}
else {
}
populateResults();
document.getElementById('CalculatedResults').style.display = "block";
} //end massive else statement that ensures all fields have values
*****Close out of the Loading message********
} //scpd results
Thank you all for your time, it is greatly appreciated
It is a good idea to separate your display code from the calculation code. It should roughly look like this
displayDialog();
makeCalculation();
closeDialog();
If you are having trouble with any of those steps, please add it to your question.
Computers are fast. Really fast. Most modern computers can do several billion instructions per second. Therefore, I'm fairly certain you can rely on a a setTimeout function to fire around 1000ms to be sufficient to show a loading message.
if (product === "Choose an Option." || product === "") {
/* ... */
} else {
/* ... */
var loader = document.getElementById('loader');
loader.style.display = 'block';
window.setTimeout(function() {
loader.style.display = 'none';
document.getElementById('CalculatedResults').style.display = "block";
}, 1000);
}
<div id="loader" style="display: none;">Please wait while we calculate.</div>
You need to give the UI main thread a chance to render your message before starting your calculation.
This is often done like this:
showMessage();
setTimeout(function() {
doCalculation();
cleanUp()
}, 0);
Using the timer allows the code to fall through into the event loop, update the UI, and then start up the calculation.
You're already using a section to pop up a "results" page -- why not pop up a "calculating" page?
Really, there are 4,000,000 different ways of tackling this problem, but why not try writing a "displayCalculatingMessage" function and a "removeCalculatingMessage" function, if you don't want to get all object-oriented on such a simple thing.
function displayCalculatingMessage () {
var submit_button = getSubmitButton();
submit_button.disabled = true;
// optionally get all inputs and disable those, as well
// now, you can either do something like pop up another hidden div,
// that has the loading message in it...
// or you could do something like:
var loading_span = document.createElement("span");
loading_span.id = "loading-message";
loading_span.innerText = "working...";
submit_button.parentElement.replaceChild(loading_span, submit_button);
}
function removeCalculatingMessage () {
var submit_button = getSubmitButton(),
loading_span = document.getElementById("loading-message");
submit_button.disabled = false;
loading_span.parentElement.replaceChild(submit_button, loading_span);
// and then reenable any other disabled elements, et cetera.
// then bring up your results div...
// ...or bring up your results div and do this after
}
There are a billion ways of accomplishing this, it all comes down to how you want it to appear to the user -- WHAT you want to have happen.