jQuery Function for Split Lists - javascript

I'm trying to build some jQuery functionality into my site and I've caught a snag. I need to split a jQuery block style menu into 2 & possibly 3 columns vs having them all in one column on top of each other. I'll post as much as I can in here. I'm sure I'm missing something blatantly obvious. I'll start with the website I'm going off of:
http://upsidestudio.com/web/splitcol/2/
Now the CSS I've got:
.tabs {
width: 700px;
font-weight: ;
margin: 0;
padding: 0px;
float: left;
}
the <head> of my html: (I think my errors would be in here: I'm new to jQuery/Javascript)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>My Site</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta name="author" content="" />
<!-- !Stylesheets -->
<link rel="stylesheet" type="text/css" href="css/screen.css" media="all" />
<!--[if IE 7]><link rel="stylesheet" href="css/ie7.css" type="text/css" media="screen" /><![endif]-->
<!--[if lte IE 8]><link rel="stylesheet" href="css/ie8.css" type="text/css" media="screen" /><![endif]-->
<!-- !jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="http://cdn.jquerytools.org/1.2.5/all/jquery.tools.min.js"></script>
<script>
// execute your scripts when the DOM is ready. this is mostly a good habit
$(function() {
// initialize scrollable
$("#browsable").scrollable({circular: true}).navigator().autoscroll({
interval: 10000
});
// initialize scrollable together with the autoscroll plugin
var root = $("#scroller").scrollable({circular: true}).autoscroll({ autoplay: false });
// perform JavaScript after the document is scriptable.
$(function() {
// setup ul.tabs to work as tabs for each div directly under div.panes
$("ul.tabs").tabs("div.panes > div")
});
});
<!-- !jQuery Split Navigation -->
$(document).ready(function() {
$('.tabs').each(function() {
if($(this).is("ol")) { var ordered = true; }
var colsize = Math.round($(this).find("li").size() / 2);
$(this).find("li").each(function(i) {
if (i>=colsize) {
$(this).addClass('right_col');
}
});
if(ordered) {
$(this).find('.right_col').insertAfter(this).wrapAll("<ol class='tabs' start='" + (colsize+1) + "'></ol>").removeClass("right_col");
} else {
$(this).find('.right_col').insertAfter(this).wrapAll("<ul class='tabs'></ul>").removeClass("right_col");
}
});
});
</script>
</head>
And Lastly...My Html section.
<!--THE TABS-->
<hr width="575" size="4" noshade align="left">
<ul class="tabs">
<li>What We Do</li>
<li>How It Works</li>
<li>FAQ</li>
<li>The Ajungo Team</li>
<li>Advertise</li>
</ul>
<hr width="575" size="4" noshade align="left"><br/><br/>
<!--TAB PANES COME IN BELOW THIS-->

Well, the biggest problem I can see there is that you've got a HTML comment stuck in the middle of the script block:
<!-- !jQuery Split Navigation -->
Remove that, then adding
.tabs {
margin-bottom: 20px;
}
And you can see that the ul.tabs list has been split in two. However, there a few inefficiencies in the script. It can be rewritten much, much more cleanly like this:
$('.tabs').each(function() {
var t = $(this), // Store a copy of both $(this) and t.children(),
children = t.children(), // to avoid calling the jQuery function too much
// Create a clone of the original list, then empty it and insert it after the original
secondList = t.clone(false).empty().insertAfter(this),
// Calculate the number of elements to move to the second list
// ie. half the number of elements in the list, divided by two and rounded up
length = Math.ceil(children.length / 2);
// Move half the children of the original list to the new one
children.slice(length).appendTo(secondList);
// If the list is an ordered list, let the list start at the correct position
if(this.nodeName === 'OL'){
secondList.attr('start', length + 1);
}
});
See: http://www.jsfiddle.net/yijiang/Tf4HT/1/

Related

Trying to animate dynamically created elements with GSAP

I am trying to animate elements that are added to the DOM via javascript with GSAP.
Here is the MRE:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<title>Recipe Search</title>
</head>
<body>
<section id="searchBackgroundImage">
<section id="searchSection">
<h1>What's In The Fridge</h1>
<button type="button" id="btn">Seach!</button>
<div id="recipeContainer"></div>
<div id="test"><h2>Test</h2></div>
</section>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>
<script text="text/javascript" src="js/main.js"></script>
</body>
</html>
CSS
h2 {
opacity: 0.1;
}
JS
document.querySelector('#btn').addEventListener('click',() => {
getRecipe();
timeline.play();
});
function getRecipe(){
let recipeTitles = `<h2>Cheese Burger</h2><h2>Ham Sandwich</h2>`
document.querySelector('#recipeContainer').innerHTML = recipeTitles
}
const timeline = gsap.timeline({
duration: 1,
paused: true
});
timeline
.to(
'#recipeContainer h2', {
opacity: 1
}
)
So I would like to change the opacity of the h2s.
It is not working because the h2s don't exist when the page first loads.
I was hoping that setting it to paused and only having it play on click would fix the problem, but unfortunately not.
If I change
timeline
.to(
'#recipeContainer h2', {
opacity: 1
}
)
to
timeline
.to(
'#test h2', {
opacity: 1
}
)
Then it works fine for that element.
So it has to be the element being dynamically created but I haven't been able to find a solution.
I've been reading the docs and it seems like I might be able to use TimelineMax and onComplete but I can't figure out how to implement it here.
Here is the codepen:
https://codepen.io/acodeaday/pen/RwJbrWa
Thank you for any help.
The problem here is that the javascript file is compiled before the click event. This means that the browser encounters the following error before the event listener is called.
Solution: Defining the timeline.to() properties inside the event listener will circumvent this problem.
document.querySelector("#btn").addEventListener("click", () => {
getRecipe();
timeline.to("#recipeContainer h2", {
opacity: 1,
});
timeline.play();
});

Difference between using tagname or e.target for addEventListener [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 11 months ago.
I want to add a line-through toggle when li is clicked.
The Only difference in below codes is javascript codes.
The problem is former one. The latter is working.
I can't find why former is not working when latter is working and written almost same.
not working code
()=>{
li.classList.toggle("remove");
}
working code
(e)=>{
e.target.classList.toggle("remove");
}
not working whole code
const lis = document.getElementsByTagName("li");
for (li of lis){
li.addEventListener("click",()=>{
li.classList.toggle("remove");
})
}
.remove {
text-decoration: line-through;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul id="sampleList">
<li id="list1">list 1</li>
<li id="list2">list 2</li>
<li id="list3">list 3</li>
</ul>
</body>
</html>
working whole code
const lis = document.getElementsByTagName("li");
for (li of lis){
li.addEventListener("click",(e)=>{
e.target.classList.toggle("remove");
})
}
.remove {
text-decoration: line-through;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<ul id="sampleList">
<li id="list1">list 1</li>
<li id="list2">list 2</li>
<li id="list3">list 3</li>
</ul>
</body>
</html>
const lis = document.getElementsByTagName("li");
for (li of lis){
li.addEventListener("click",()=>{
li.classList.toggle("remove");
})
}
li is not a tag name (except inside the string on line one).
It is a variable name declared here:
for (li of lis){
Since you didn't use var, const, or let, it is an implicit global.
Every event listener you are using is referring to the same global variable, which holds the last value you assigned to it.
You need to scope it (with let) so you get a unique variable for each iteration around the for loop (and thus for the arrow functions you pass to addEventListener).
for (let li of lis) {
The iteration "assigns" each matching selected element to the "li" variable from first to last. By the time you click them the last element selected is the one assigned to the "li" variable (since it is overriding it each time). That's why when you click any of them it changes the last.
What you want is to reference the clicked element, not the "li" variable per se, hence the second code working (because it references the target of the "click" event)
You can try this next approach for your first method to work.
You can loop through every one of the Nodelist items by setting var i = 0 or let i = 0 and then iterate over the NodeList'
s length.
Every time you would toggle a list item, you would be assigning a scoped let or var variable for a unique click on each item.
The loop => for(var i = 0; i < lis.length; i++) or for(let i = 0; i < lis.length; i++) and set the classlist of your e.target (event target).
That must do the work.
const lis = document.getElementsByTagName("li");
for(var i = 0; i < lis.length; i++){
lis[i].addEventListener("click", (e) => {
e.target.classList.toggle("remove");
});
}
.remove {
text-decoration: line-through;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul id="sampleList">
<li id="list1">list 1</li>
<li id="list2">list 2</li>
<li id="list3">list 3</li>
</ul>
</body>
</html>

jQuery Image Warp script issues [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am currently attempting to execute this on my site http://www.dynamicdrive.com/dynamicindex4/imagewarp.htm. It seems easy, I have currently called all scripts in my section and called the class in the image I where I want the it. Here is my
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="description" content="Reflecting our present perception of aesthetics.">
<meta name="keywords" content="">
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=1, user-scalable=no" />
<meta name="robots" content="INDEX,FOLLOW" />
<meta property="og:url" content="" />
<meta property="og:title" content="" />
<meta property="og:image" content="" />
<meta property="og:description" content="" />
<title><?php bloginfo('name'); ?></title>
<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
<link rel="icon" type="image/x-icon" href="" />
<link rel="stylesheet" href="<?php bloginfo('stylesheet_media-queries.css'); ?>" type="text/css" />
<!-- jquery -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<!-- fontawesome -->
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>
<?php wp_head(); ?>
<script type="text/javascript" src="http://www.dynamicdrive.com/dynamicindex4/jquery.imageWarp.js">
/***********************************************
* jQuery imageWarp script- (c) Dynamic Drive DHTML code library (www.dynamicdrive.com)
* Please keep this notice intact
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for this script and 100s more
***********************************************/
</script>
<script type="text/javascript">
jQuery(document).ready(function($){
$('img.imagewarp').imageWarp() //apply warp effect to images with CSS class "imagewarp"
})
</script>
</head>
and this is how my image looks
<img src="emb.png" class="imagewarp">
The effect does not seem to appear. Any ideas? Thank you!
See below if it helps i added the script file here as there was no https or cdn link availables .
/* imageWarp jQuery plugin v1.01
* Last updated: June 29th, 2009. This notice must stay intact for usage
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code
*/
jQuery.noConflict()
jQuery.imageWarp={
dsettings: {
warpfactor: 1.5, //default increase factor of enlarged image
duration: 1000, //default duration of animation, in millisec
imgopacity: [0.5, 1],
warpopacity: [0.1, 0.5]
},
warpshells: [],
refreshoffsets:function($target, warpshell){
var $offsets=$target.offset()
warpshell.attrs.x=$offsets.left //update x position of original image relative to page
warpshell.attrs.y=$offsets.top
warpshell.newattrs.x=warpshell.attrs.x-((warpshell.newattrs.w-warpshell.attrs.w)/2) //update x position of final warped image relative to page
warpshell.newattrs.y=warpshell.attrs.y-((warpshell.newattrs.h-warpshell.attrs.h)/2)
},
addEffect:function($, $target, options){
var setting={} //create blank object to store combined settings
var setting=jQuery.extend(setting, this.dsettings, options)
var effectpos=this.warpshells.length
var attrs={w:$target.outerWidth(), h:$target.outerHeight()}
var newattrs={w:Math.round(attrs.w*setting.warpfactor), h:Math.round(attrs.h*setting.warpfactor)}
var $clone=$target.clone().css({position:'absolute', left:0, top:0, visibility:'hidden', border:'1px solid gray', zIndex:1000}).appendTo(document.body)
$target.add($clone).data('pos', effectpos) //save position of image
var $targetlink=$target.parents('a').eq(0)
this.warpshells.push({$clone:$clone, attrs:attrs, newattrs:newattrs, $link:($targetlink.length==1)? $targetlink : null}) //remember info about this warp image instance
$target.click(function(e){
var $this=$(this).css({opacity:setting.imgopacity[0]})
var imageinfo=jQuery.imageWarp.warpshells[$(this).data('pos')]
jQuery.imageWarp.refreshoffsets($this, imageinfo) //refresh offset positions of original and warped images
if (imageinfo.$link){
e.preventDefault()
}
var $clone=imageinfo.$clone
$clone.stop().css({left:imageinfo.attrs.x, top:imageinfo.attrs.y, width:imageinfo.attrs.w, height:imageinfo.attrs.h, opacity:setting.warpopacity[0], visibility:'visible'})
.animate({opacity:setting.warpopacity[1], left:imageinfo.newattrs.x, top:imageinfo.newattrs.y, width:imageinfo.newattrs.w, height:imageinfo.newattrs.h}, setting.duration,
function(){ //callback function after warping is complete
$clone.css({left:0, top:0, visibility:'hidden'})
$this.css({opacity:setting.imgopacity[1]})
if (imageinfo.$link){
window.location=imageinfo.$link.attr('href')
}
}) //end animate
}) //end click
}
};
jQuery.fn.imageWarp=function(options){
var $=jQuery
return this.each(function(){ //return jQuery obj
var $imgref=$(this)
if (this.tagName!="IMG")
return true //skip to next matched element
if (parseInt($imgref.css('width'))>0 && parseInt($imgref.css('height'))>0){ //if image has explicit width/height attrs defined
jQuery.imageWarp.addEffect($, $imgref, options)
}
else if (this.complete){ //account for IE not firing image.onload
jQuery.imageWarp.addEffect($, $imgref, options)
}
else{
$(this).bind('load', function(){
jQuery.imageWarp.addEffect($, $imgref, options)
})
}
})
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script src="http://www.dynamicdrive.com/dynamicindex4/jquery.imageWarp.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($){
$('img.imagewarp').imageWarp();
})
</script>
<img src="http://www.mondieu.nu/mag/wp-content/uploads/2017/12/emb.png" class="imagewarp">

jQuery mobile collapsed list view with search not working

I have created a listview in jquery with a listdivider with a filter. The filter works as expected but as soon as you collapse either of the list dividers, the search subsequently does not work at all,
<!DOCTYPE html>
<html>
<head>
<title>jQuery Mobile page</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href=" <link rel="stylesheet" href="<%=request.getContextPath()%>/css/mobile/jquery.mobile.structure-1.3.1.min.css" />
<script src="<%=request.getContextPath()%>/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
jQuery(document).bind("mobileinit", function () {
jQuery.mobile.ajaxEnabled = false;
});
</script>
<script src="<%=request.getContextPath()%>/js/mobile/jquery.mobile-1.3.1.min.js"></script>
<script>
var hide=0;
var dpwClone='';
$(function(){
$('[data-role="list-divider"]').click(function(element){
$(this).nextUntil('[data-role="list-divider"]').toggle();
$("#eServiceList").listview("refresh");
// $(this).nextUntil('[data-role="list-divider"]').toggle();
});
$( "#eServiceList" ).listview( "option", "filterCallback", searchList);
function searchList( text, searchValue, item ) {
var result = text.toString().toLowerCase().indexOf( searchValue.toString().toLowerCase() );
var show = false;
var hide = true;
if (result == -1 )
return hide;
return show;
};
});
</script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Problem nested list views</h1>
</div>
<div data-role="content">
<div class="content-primary">
<ul data-role="listview" data-inset="true" data-divider-theme="d" data-filter="true" id="eServiceList">
<li data-role="list-divider" id="dpw" >
DPW
</li>
<li>Inbox</li>
<li>Outbox</li>
<li data-role="list-divider" id="custo">
Customs
</li>
<li>Friends</li>
<li>Work</li>
</ul>
</div>
</div>
</div>
<script>
</script>
</body>
</html>
Below is the JSfiddle link.
http://jsfiddle.net/jsfiddle_one/R8pZH/
Using .toggle() adds to the element an inline style attribute style="display: none;" or style="display: block;". List items are already enhanced with display: block; by jQuery Mobile. Hence, when using .toggle() - when it is visible again - the element will get display: block; twice, inline and in CSS style sheet.
To overcome this problem, use .toggleClass() classes rather than inline styling. I fixed your problem by adding a class
.hide { display: none !important; }
and I used it with .toggleClass('hide');
New code
Using custom CSS classes to override existing CSS is safer, and keep in mind that for jQuery Mobile, it's better to end each property with !important to force override.

Jquery CSS Scope Doesn't Work Properly on selectmenu

My page:JSP+Struts2 tags+JQuery Library+JqueryUI
I have a JQuery selectmenu and two JQuery UI themes, i want to style the selectmenu with the second JQuery UI theme(css scope), but the content area(background of option tags) of my selectmenu is styled with the first theme!
What should I do?
here are some of my code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# taglib prefix="s" uri="/struts-tags"%>
<%# taglib prefix="sj" uri="/struts-jquery-tags"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<sj:head jqueryui="true" jquerytheme="orange" customBasepath="css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* selectmenu css */
fieldset { border:0; margin-bottom: 40px;}
label,select,.ui-select-menu { float: right; }
select { }
/*select with custom icons*/
body a.customicons { height: 2.8em;}
body .customicons li a, body a.customicons span.ui-selectmenu-status { line-height: 2em; padding-left: 30px !important; }
body .video .ui-selectmenu-item-icon, body .podcast .ui-selectmenu-item-icon, body .rss .ui-selectmenu-item-icon { height: 24px; width: 24px; }
/* /selectmenu css */
</style>
<!-- JQuery --><link type="text/css" href="css/orange/jquery-ui.custom.css" rel="stylesheet"/>
<!-- JQuery --><script type="text/javascript" src="js/jquery-ui.custom.min.js"></script>
<!-- interiorTheme --><link type="text/css" rel="Stylesheet" href="css/interior_uilightness/jquery-ui-1.8.13.custom.css">
<!-- selectMenu --><link type="text/css" rel="Stylesheet" href="css/element/jquery.ui.selectmenu.css">
<!-- selectMenu --><script type="text/javascript" src="js/element/jquery.ui.selectmenu.js"></script>
<script type="text/javascript">
//--selectmenu
$(function(){
$('select#buy_groupBy').selectmenu({
width: 220,
maxHeight: 400,
style:'popup',
format: addressFormatting
});
});
//a custom format option callback
var addressFormatting = function(text){
var newText = text;
//array of find replaces
var findreps = [
{find:/^([^\-]+) \- /g, rep: '<span class="ui-selectmenu-item-header">$1</span>'},
{find:/([^\|><]+) \| /g, rep: '<span class="ui-selectmenu-item-content">$1</span>'},
{find:/([^\|><\(\)]+) (\()/g, rep: '<span class="ui-selectmenu-item-content">$1</span>$2'},
{find:/([^\|><\(\)]+)$/g, rep: '<span class="ui-selectmenu-item-content">$1</span>'},
{find:/(\([^\|><]+\))$/g, rep: '<span class="ui-selectmenu-item-footer">$1</span>'}
];
for(var i in findreps){
newText = newText.replace(findreps[i].find, findreps[i].rep);
}
return newText;
}
//--/selectmenu
</script>
</head>
<body>
<div class="interior_UILightness">
<s:form action="buy.action" method="post" onsubmit="return validateBuy()" cssStyle="margin-top:-5px;">
<tr><td></td><td><s:hidden name="selectedGame"/></td></tr>
<s:select name="groupBy" label="xxxx" list="#{'1':'1','2':'2','3':'3'}" cssStyle="width:220px;"/>
<s:textfield name="symbol" label="xxxx" readonly="true" cssClass="strutsBuyTextField"/>
<s:textfield id="price" name="price" maxlength="16" label="xxxx" readonly="true" cssClass="strutsBuyTextField"/>
<s:textfield name="shares" maxlength="7" label="xxxx" cssClass="strutsBuyTextField" onkeyup="showDetails();" onkeydown="hideMessage();"/>
<s:submit value="xxxx" name="buySubmit" cssClass="submit" cssStyle="margin-right:80px"/>
</s:form>
</div>
</body>
</html>
I think you need to add the CSS scope before you download a custom theme. The struts jQuery plugin custom base path is used to specify the path to the theme if it is not in the default directory.
So, I think you need to download the custom theme and supply a CSS scope and also a theme folder name and then change the customBasepath to the directory with the theme folder name.
I know the question was asked over 3 years ago but I will answer it for those ( like me ) who found this topic while looking for the exact same problem.
I assume that your select box is placed in some div with the CSS scope of the second theme, e.g:
<div class="scope2" id="select-div">
<select id="select"></select>
</div>
In such case, if you take a look at the API of the selectmenu, you can find the information about appendTo property of the menu. If no value is passed, the div containing the expandable menu will be placed somewhere in the body of the page, probably at the bottom. In such case, the div with '' and all the <li> elements will not be placed in scope of the scope2 class and that is why the menu is styled with first theme.
$('#select').selectmenu( { appendTo : '#select-div' } ); will do the trick

Categories