Show/Hide Only Working in Chrome (jQuery) - javascript

This question has been asked before, in different context (works in Firefox, not Chrome).
My show/hide functions are not working in Firefox, but they are working fine in Chrome. Technically, it works ONCE in Firefox, then it will not work again until I refresh the page. Again, works fine in Chrome and Internet Explorer.
jQuery v1.11.1
Firefox v40.0.3
Chrome v45.0.2454.93
**** UPDATE: **** I fixed the problem: I replaced the code under "jQuery" with the following code.
/* Show Product Overlay */
function enlargeProduct() {
$('#productOverlay').toggle('fast', 'linear', 'closeProductOverlay()');
}
function closeProductOverlay() {
/* Hide Product Overlay */
$(document).on('click', function (event) {
if (!$(event.target).closest('#clickControl').length) {
$('#productOverlay').hide();
}
});
}
jQuery -- OLD CODE that didn't work:
function enlargeProduct() {
/* Show Hidden Div Overlay */
$('#productOverlay').show();
};
function closeProductOverlay() {
/* Hide Product Overlay */
$(document).on('click', function (event) {
if (!$(event.target).closest('#clickControl').length) {
$('#productOverlay').hide();
}
});
}
HTML to Show/Hide
<!-- Product Overlay -->
<div id="productOverlay" onclick="closeProductOverlay()">
<div id="mobiPadding">
<div id="productContainer">
<div id="clickControl">
<input type="number" onchange="addQuantity()" value="1" min="1" max="99" />
<input type="button" class="btn btn-primary" onclick="addToCart()" value="Add to Cart" />
</div>
</div>
</div>
</div>
HTML Control - This is the div container into which I populate the HTML
<div class="item-container container">
</div>
Javascript to Populate HTML Control
var item = document.getElementsByClassName("item-container")[0];
var items = json.items;
for (var i = 0; i < items.length; i++) {
/* Outermost Div - For Bootstrap Formatting */
var div = document.createElement("div");
var divClass = document.createAttribute("class");
divClass.value = "col-md-3";
div.setAttributeNode(divClass);
item.appendChild(div);
/* Center Div - For adding Padding to each box */
var div2 = document.createElement("div");
var divClass = document.createAttribute("class");
divClass.value = "itemDiv";
div2.setAttributeNode(divClass);
div.appendChild(div2);
/* Innermost Div - For Adding Hover Effects (Not visible, functionality only) */
var hoverDiv = document.createElement("div");
var divClass = document.createAttribute("class");
divClass.value = "hoverDiv";
hoverDiv.setAttributeNode(divClass);
divClass = document.createAttribute("onmouseover");
divClass.value = "onMouseOver(" + i + ")";
hoverDiv.setAttributeNode(divClass);
divClass = document.createAttribute("onmouseout");
divClass.value = "onMouseOut(" + i + ")";
hoverDiv.setAttributeNode(divClass);
/* Add new ID iteration to identify selected product for button toggle */
var divId = document.createAttribute("id");
divId.value = "btn" + i;
hoverDiv.setAttributeNode(divId);
div2.appendChild(hoverDiv);
/* Add clearfix to clear formatting after each fourth iteration */
if (i >= 0) {
var j = i - 3;
if (j % 4 == 0) {
var clearfix = document.createElement("div");
var fixClass = document.createAttribute("class");
fixClass.value = "clearfix";
clearfix.setAttributeNode(fixClass);
item.appendChild(clearfix);
}
}
/* Title */
var h2 = document.createElement("h4");
h2.innerHTML = items[i].title.text;
hoverDiv.appendChild(h2);
/* Class */
var titleClass = document.createAttribute('class');
titleClass.value = "titleClass";
h2.setAttributeNode(titleClass);
/* Image */
var img = document.createElement("img");
var src = document.createAttribute('src');
src.value = items[i].image.text;
img.setAttributeNode(src);
hoverDiv.appendChild(img);
/* Class */
var imageClass = document.createAttribute('class');
imageClass.value = "imageClass";
img.setAttributeNode(imageClass);
/* Description */
var p = document.createElement("p");
p.innerHTML = items[i].description.text;
hoverDiv.appendChild(p);
/* Class */
var descClass = document.createAttribute('class');
descClass.value = "descriptionClass";
p.setAttributeNode(descClass);
/* Price */
var price = document.createElement("p");
price.innerHTML = items[i].price.text;
hoverDiv.appendChild(price);
/* Class */
var priceClass = document.createAttribute('class');
priceClass.value = "priceClass";
price.setAttributeNode(priceClass);
/* Hidden Click to Enlarge Product Button - Show/Hide on Hover*/
var productButton = document.createElement("div");
productButton.innerHTML = '<input id="productBtn' + i + '" onclick="enlargeProduct()" class="productBtn btn btn-primary" value="Click to Enlarge"/>';
hoverDiv.appendChild(productButton);
};
/* DOM Event Listeners - Handle Mouse Over/Out to Toggle Button and Product Overlays */
function onMouseOver(i) {
$('#productBtn' + i).show();
}
function onMouseOut(i) {
$('#productBtn' + i).hide();
}
I populate the item array with JSON. Is this necessary to include as well? Essentially they are set up like this:
var json = {
"items": [
{
"title": { "text": "#PART0001" },
"image": { "text": "../items/sale-october/PART0001.jpg" },
"description": { "text": "Item Description" },
"price": { "text": "$99.99" }
}
]
};
I'm especially confused, because I used this exact method for another section of my website (show/hiding a signup form), and that works just fine.
Soooo what am I doing wrong here? =/

Solved it:
Replaced the code under jQuery with the following:
/* Show Product Overlay */
function enlargeProduct() {
$('#productOverlay').toggle('fast', 'linear', 'closeProductOverlay()');
}
function closeProductOverlay() {
/* Hide Product Overlay */
$(document).on('click', function (event) {
if (!$(event.target).closest('#clickControl').length) {
$('#productOverlay').hide();
}
});
}
Seems that toggle is a way better way to do this. Still not entirely sure why the original didn't work, but I am happy! Hope this helps someone!

Related

Dynamically expand <input> element with text

I feel like this should be easy. I've been searching around / trying things out for at least a week, and still to no avail.
I'd like an <input> element with placeholder text. I'd like the element to only be as wide as the placeholder text. When you click into the <input>, I'd like the width to remain the same. As you type, if your input text exceeds the width of the original placeholder text (and therefore the <input> element itself), I'd like the <input> to expand to accommodate the text.
Thoughts, SO?
Here is one attempt (in vanilla javascript) at a working solution which takes into account different font sizes, different character widths etc.:
function reviewWidth(startWidth) {
/* Grab various elements */
var hiddenSpan = document.getElementsByClassName('hidden')[0];
var inputValue = document.getElementsByTagName('input')[0].value;
/* Update text content of hiddenSpan */
hiddenSpan.innerHTML = inputValue;
/* Update <input> width */
var hiddenSpanStyles = getComputedStyle(hiddenSpan);
var newWidth = parseInt(hiddenSpanStyles.getPropertyValue('width'));
if (newWidth > startWidth) {
input.style.width = newWidth + 'px';
}
else {
input.style.width = startWidth + 'px';
}
}
/* Grab various elements */
var body = document.getElementsByTagName('body')[0];
var input = document.getElementsByTagName('input')[0];
var placeholder = input.getAttribute('placeholder');
/* Create hiddenSpan */
var hiddenSpan = document.createElement('span');
var placeholderText = document.createTextNode(placeholder);
hiddenSpan.appendChild(placeholderText);
/* Style hiddenSpan */
var inputStyles = getComputedStyle(input);
hiddenSpan.style.fontFamily = inputStyles.getPropertyValue('font-family');
hiddenSpan.style.fontSize = inputStyles.getPropertyValue('font-size');
hiddenSpan.style.borderLeftWidth = inputStyles.getPropertyValue('border-left-width');
hiddenSpan.style.paddingLeft = inputStyles.getPropertyValue('padding-left');
hiddenSpan.style.paddingRight = inputStyles.getPropertyValue('padding-right');
hiddenSpan.style.borderRightWidth = inputStyles.getPropertyValue('border-right-width');
hiddenSpan.style.display = 'inline-block';
hiddenSpan.style.opacity = '0';
hiddenSpan.classList.add('hidden');
/* Add hiddenSpan to document body */
body.appendChild(hiddenSpan);
/* Initialise <input> width */
var hiddenSpanStyles = getComputedStyle(hiddenSpan);
var startWidth = parseInt(hiddenSpanStyles.getPropertyValue('width'));
input.style.width = startWidth + 'px';
/* Run reviewWidth() function once */
if (input.value != '') {
reviewWidth(startWidth);
}
/* Add Event Listener to <input> to trigger reviewWidth() function */
input.addEventListener('input',function(){reviewWidth(startWidth);},false);
input {
font-family: arial, sans-serif;
font-size: 0.8em;
padding: 2px;
}
<input type="text" placeholder="Example Placeholder" />
I added some minor improvements to #Rounin's answer to make my own attempt:
Parsing consecutive spaces in HTML compresses to one space unless they're non-breaking, so I mapped to &nbsp. In addition, I mapped < to < to escape HTML. The reason I did not use textContent instead of innerHTML was because there's no way to inject non-breaking spaces into textContent.
The hidden span is no longer part of the DOM when it is not needed, so it doesn't trigger the parent element to scroll when it's too wide.
the pixel values for width are actually floats, not integers, so using parseFloat instead of parseInt makes the <input/> width more precise.
I trimmed down some of the code to reduce verbosity while trying to maintain readability.
/* Set up */
var regExp = /[ <]/g;
function replacer(c) {
return {
' ': ' ',
'<': '<'
}[c];
}
/* Grab various elements */
var body = document.querySelector('body');
var input = document.querySelector('input');
var placeholder = input.getAttribute('placeholder');
/* Create hiddenSpan */
var hiddenSpan = document.createElement('span');
hiddenSpan.innerHTML = placeholder.replace(regExp, replacer);
/* Style hiddenSpan */
var inputStyles = getComputedStyle(input);
['font', 'padding', 'border', 'display'].forEach(function(prop) {
hiddenSpan.style[prop] = inputStyles.getPropertyValue(prop);
});
hiddenSpan.style.visibility = 'hidden';
hiddenSpan.style.pointerEvents = 'none';
var hiddenSpanStyles = getComputedStyle(hiddenSpan);
/* Initialise <input> width */
body.appendChild(hiddenSpan);
var startWidth = parseFloat(hiddenSpanStyles.getPropertyValue('width'));
body.removeChild(hiddenSpan);
function reviewWidth() {
var inputValue = input.value;
/* Update text content of hiddenSpan */
hiddenSpan.innerHTML = inputValue.replace(regExp, replacer);
body.appendChild(hiddenSpan);
/* Update <input> width */
var newWidth = parseFloat(hiddenSpanStyles.getPropertyValue('width'));
body.removeChild(hiddenSpan);
if (newWidth > startWidth) {
input.style.width = newWidth + 'px';
} else {
input.style.width = startWidth + 'px';
}
}
reviewWidth();
/* Add Event Listener to <input> to trigger reviewWidth() function */
input.addEventListener('input', reviewWidth, false);
input {
font-family: arial, sans-serif;
font-size: 0.8em;
padding: 2px;
}
<input type="text" placeholder="Example Placeholder" />
Feel free to leave comments if you have questions or suggestions to improve this answer.

Javascript external function with event handler to generate DOM elements is not outputting html

I am trying to dynamically generate and remove input boxes based on selection. However, I have been tweaking this code for hours but can't figure out why it's not generating the html elements.
<!DOCTYPE html><html><head><title> Calculator</title>
<link rel="stylesheet" href="css/main.css." type="text/css"
<script src="js/addInputs.js"></script>
<script>
function addListeners() {
if (window.addEventListener) {
document.getElementById('sel_value').addEventListener("change", yourSelection, false);
}
function youSelection() {
// create three inputs with three labels fro array
if (document.getElementById('sel_value').value == 1) { addInputs(4,panel01);}
// create six inputs with six labels from array
else if (document.getElementById('sel_value').value == 2) { addInputs(6,panel02);}
else {
//clear panel 1
var remove_p01 = document.getElementById('panel01');
remove_p01.parentNode.removeChild(remove_p01);
// clear panel 2
var remove_p02 = document.getElementById('panel02');
remove_p02.parentNode.removeChild(remove_p02);
}
}
}
window.onload = addListeners;
</script></head><body>
// HTML Code
<div id="container">
<label for="addinputs">No. of Ports</label><!-- lablel for selector--->
<input id="sel_value" type="number" min="0" max="3" /><br />
</div></div></body></html>
// External Javascript File
function addInputs(num_of_inputs, div_id) {
"use strict";
var main_container, div, fieldLabel, input, count, label_array;
// Labels for input fields
label_array = ["Name", "Height", "Width", "Depth", "Position x", "Position Y"];
// main container id
main_container.document.getElementById('container');
// this div is to hold the input fields
div.document.createElement('div');
div.id = div_id;
// create labels and inputs
while (count < num_of_inputs) {
fieldLabel.createElement('input');
fieldLabel.type = "text";
fieldLabel.value = label_array[count];
fieldLabel.id = "r-port_label" + count;
input.document.createElement('input');
input.type = "number";
input.value = "0";
input.id = "r_port_input" + count;
// attach inputs and labels to parent div
div.appendChild(fieldLabel);
div.appendChild(input);
//increment input fields & labels
count += 1;
}
// attach parent div to page container
main_container.appendChild(div);
}
//CSS Code
#container{
width: 400px; min-height: 400px; background: #eeeeee;
}
I think you have a typo, should'nt this:
main_container.document.getElementById('container');
div.document.createElement('div');
fieldLabel.createElement('input');
input.document.createElement('input');
be:
main_container = document.getElementById('container');
div = document.createElement('div');
fieldLabel = document.createElement('input');
input = document.createElement('input');
Wow this look like a disaster. You have like 1000 errors, it looks like somebody delibretly scramble code. Anyhow there you go code that will do something, you adjust it how you wish.
You have:
wrong function calling in your listener
missing quotes when you passing ID of panels
not initialized counter
false element creation
luckily you have "user strict" :o)
function addInputs(num_of_inputs, div_id) {
"use strict";
var main_container, div, fieldLabel, input, count, label_array;
// Labels for input fields
label_array = ["Name", "Height", "Width", "Depth", "Position x", "Position Y"];
// main container id
main_container = document.getElementById('container');
// this div is to hold the input fields
div = document.createElement('div');
div.id = div_id;
// create labels and inputs
count = 0;
while (count < num_of_inputs) {
fieldLabel = document.createElement('input');
fieldLabel.type = "text";
fieldLabel.value = label_array[count];
fieldLabel.id = "r-port_label" + count;
input = document.createElement('input');
input.type = "number";
input.value = "0";
input.id = "r_port_input" + count;
// attach inputs and labels to parent div
div.appendChild(fieldLabel);
div.appendChild(input);
//increment input fields & labels
count += 1;
}
// attach parent div to page container
main_container.appendChild(div);
}
function addListeners() {
if (window.addEventListener) {
document.getElementById('sel_value').addEventListener("change",
function (){
// create three inputs with three labels fro array
if (document.getElementById('sel_value').value == 1) { addInputs(4,'panel01');}
// create six inputs with six labels from array
else if (document.getElementById('sel_value').value == 2) { addInputs(6,'panel02');}
else {
//clear panel 1
var remove_p01 = document.getElementById('panel01');
remove_p01.parentNode.removeChild(remove_p01);
// clear panel 2
var remove_p02 = document.getElementById('panel02');
remove_p02.parentNode.removeChild(remove_p02);
}
}
, false);
}
}
window.onload = addListeners;
#container{
width: 400px; min-height: 400px; background: #eeeeee;
}
<div id="container">
<label for="addinputs">No. of Ports</label><!-- lablel for selector--->
<input id="sel_value" type="number" min="0" max="3" /><br />
</div>
Hope it will help

I want to move items with jquery but html structure is conflicting on ie8

I need help; If last Menu in first column bigger size than all li items in second column; I want to move last Menu in first column to top of second column then remove the cloned menu.
It is working on chrome but not working on ie8. What is the solution? If you have better idea for this work, please tell me..
Thanks..
<style>
.col3 { width:33.33333333333333%; float:left; }
</style>
$(document).ready(function () {
col1="<div class=\"col3\"><ul><li><h3>Menu1</h3></li><li>Child1</li></ul><ul><li><h3>Menu2</h3></li><li>Child1</li><li>Child2</li><li>Child3</li><li>Child4</li><li>Child5</li></ul></div>"
col2="<div class=\"col3\"><ul><li><h3>Menu3</h3></li><li>Child1</li><li>Child2</li><li>Child3</li><li>Child3</li></ul></div>"
tmp=col1+col2;
a1 = $(tmp)[0].innerHTML;
a2 = $(tmp)[0];
var LastUl = $(a2).children('ul:last-child')[0].outerHTML;
var LastLiSize = $(LastUl).children('li').size();
var b1 = $(tmp)[1].innerHTML;
var b2 = $(tmp)[1];
col2LiSize = $(b1).children('li').size();
if (LastLiSize > col2LiSize) {
var lastUl = a1.lastIndexOf("<ul>");
var clone = a1.substring(lastUl);
var col1tmp = a1.replace(clone, "");
var col2tmp = $(col2);
col2tmp.prepend($(clone));
result=' <div class=\"col3\">' + col1tmp + '</div> <div class=\"col3\">' + $(col2tmp).html() + '</div>';
$('body').append('<div style=\"clear:both;\">'+result+'</div>');
}
else {
$('body').append('<div style=\"clear:both;\">'+tmp+'</div>');
}
});

Previewing form using javascript in lightbox popup

please I need some help in previewing a form in popup. I have a form, quite big, so I added the option of preview to show as popup. The lightbox form popup works well, but the problem I now have is function passform() passing the inputs(textfield, select, checkbox, radio) into the popup page for preview on Click().
Below are my javascript and html codes. I left the css and some html out, because I think they're not necessary. I will appreciate your help. Thank you
The Javascript
function gradient(id, level)
{
var box = document.getElementById(id);
box.style.opacity = level;
box.style.MozOpacity = level;
box.style.KhtmlOpacity = level;
box.style.filter = "alpha(opacity=" + level * 100 + ")";
box.style.display="block";
return;
}
function fadein(id)
{
var level = 0;
while(level <= 1)
{
setTimeout( "gradient('" + id + "'," + level + ")", (level* 1000) + 10);
level += 0.01;
}
}
// Open the lightbox
function openbox(formtitle, fadin)
{
var box = document.getElementById('box');
document.getElementById('shadowing').style.display='block';
var btitle = document.getElementById('boxtitle');
btitle.innerHTML = formtitle;
if(fadin)
{
gradient("box", 0);
fadein("box");
}
else
{
box.style.display='block';
}
}
// Close the lightbox
function closebox()
{
document.getElementById('box').style.display='none';
document.getElementById('shadowing').style.display='none';
}
//pass form fields into variables
var divexugsotherugsexams1 = document.getElementById('divexugsotherugsexams1');
var exugsotherugsexams1 = document.form4.exugsotherugsexams1.value;
function passform()
{
divexugsotherugsexams1.innerHTML = document.form4.exugsotherugsexams1.value;
}
The HTML(with just one text field try):
<p><input name="submit4" type="submit" class="button2" id="submit4" value="Preview Note" onClick="openbox('Preview Note', 1)"/>
</p>
<div id="shadowing"></div>
<div id="box">
<span id="boxtitle"></span>
<div id="divexugsotherugsexams1"></div>
<script>document.write('<PARAM name="SRC" VALUE="'+exugsotherugsexams1+'">')</script>
Close
</div>

Custom styled select box

am trying to use javascript for custom styled select boxes from www.gerrendesign.com/entry_images/selectboxdemo.zip
and as I have plenty entries inside one of select box I need to make but am stuck in creation of scrolling function.
As this select boxes are compatible with almost all older and new browsers. I need only suggestion or solution how to add scroll in this linked/attached files above - if select box is populated with plenty of entries (example cities, states, or exchange rates...)
Am stuck here...
Thanks for your cooperation
Ivan
THIS IS CODE:
$(document).ready(function(){
// first locate all of the select tags on the page and hide them
$("select.changeMe").css('display','none');
//now, for each select box, run this function
$("select.changeMe").each(function(){
var curSel = $(this);
// get the CSS width from the original select box
var gddWidth = $(curSel).css('width');
var gddWidthL = gddWidth.slice(0,-2);
var gddWidth2 = gddWidthL - 28;
var gddWidth3 = gddWidthL - 16;
// build the new div structure
var gddTop = '<div style="width:' + gddWidthL + 'px" class="selectME" tabindex="0"><div class="cornerstop"><div><div></div></div></div><div class="middle"><div><div><div>';
//get the default selected option
var whatSelected = $(curSel).children('option:selected').text();
//write the default
var gddFirst = '<div class="first"><span class="selectME gselected" style="width:'+ gddWidth2 + 'px;">'+ whatSelected +'</span><span id="arrowImg"></span><div class="clears"></div></div><ul class="selectME">';
// create a new array of div options from the original's options
var addItems = new Array();
$(curSel).children('option').each( function() {
var text = $(this).text();
var selVal = $(this).attr('value');
var before = '<li style="width:' + gddWidthL + 'px;"><a href="#" rel="' + selVal + '" tabindex="0" style="width:' + gddWidth3 + 'px;">';
var after = '</a></li>';
addItems.push(before + text + after);
});
//hide the default from the list of options
var removeFirst = addItems.shift();
// create the end of the div selectbox and close everything off
var gddBottom ='</ul></div></div></div></div><div class="cornersbottom"><div><div></div></div></div></div>'
//write everything after each selectbox
var GDD = gddTop + gddFirst + addItems.join('') + gddBottom;
$(curSel).after(GDD);
//this var selects the div select box directly after each of the origials
var nGDD = $(curSel).next('div.selectME');
$(nGDD).find('li:first').addClass("first");
$(nGDD).find('li:last').addClass('last');
//handle the on click functions - push results back to old text box
$(nGDD).click( function(e) {
var myTarA = $(e.target).attr('rel');
var myTarT = $(e.target).text();
var myTar = $(e.target);
//if closed, then open
if( $(nGDD).find('li').css('display') == 'none')
{
//this next line closes any other selectboxes that might be open
$('div.selectME').find('li').css('display','none');
$(nGDD).find('li').css('display','block');
//if user clicks off of the div select box, then shut the whole thing down
$(document.window || 'body').click( function(f) {
var myTar2 = $(f.target);
if (myTar2 !== nGDD) {$(nGDD).find('li').css('display','none');}
});
return false;
}
else
{
if (myTarA == null){
$(nGDD).find('li').css('display','none');
return false;
}
else {
//set the value of the old select box
$(curSel).val(myTarA);
//set the text of the new one
$(nGDD).find('span.gselected').text(myTarT);
$(nGDD).find('li').css('display','none');
return false;
}
}
//handle the tab index functions
}).focus( function(e) {
$(nGDD).find('li:first').addClass('currentDD');
$(nGDD).find('li:last').addClass('lastDD');
function checkKey(e){
//on keypress handle functions
function moveDown() {
var current = $(nGDD).find('.currentDD:first');
var next = $(nGDD).find('.currentDD').next();
if ($(current).is('.lastDD')){
return false;
} else {
$(next).addClass('currentDD');
$(current).removeClass('currentDD');
}
}
function moveUp() {
var current = $(nGDD).find('.currentDD:first');
var prev = $(nGDD).find('.currentDD').prev();
if ($(current).is('.first')){
return false;
} else {
$(prev).addClass('currentDD');
$(current).removeClass('currentDD');
}
}
var curText = $(nGDD).find('.currentDD:first').text();
var curVal = $(nGDD).find('.currentDD:first a').attr('rel');
switch (e.keyCode) {
case 40:
$(curSel).val(curVal);
$(nGDD).find('span.gselected').text(curText);
moveDown();
return false;
break;
case 38:
$(curSel).val(curVal);
$(nGDD).find('span.gselected').text(curText);
moveUp();
return false;
break;
case 13:
$(nGDD).find('li').css('display','none');
}
}
$(document).keydown(checkKey);
}).blur( function() {
$(document).unbind('keydown');
});
});
});
You could render the list inside a div, that has either a fixed height or a max-height (depending on your cross-browser requirements). Presuming the default scroll bar is ok...
If structure is something in the direction of
<div class="select_data_container">
<ul class="select_rows">
<li>row1</li>
<li>row2</li>
</ul>
</div>
CSS-example could be
.select_data_container {overflow-y: auto; height: 200px;}
.select_rows {display:block;}

Categories