i want to display the following Post in 3 different sections. The first section is the table of content. The second is the summary and the third is the theory. Is like a multipage post but each page has a section, as I don't want to show all the information in a single page.
Thanks in advance
The way I have come up with this is this way.
I'm only posting these because I have it all setup so I can basically copy and paste it in. Next time I want to see more effort on your part.
Create a new JS file. well call it mytabs.js in that file put this:
;( function( $, window, document, undefined ) {
"use strict";
$( document ).ready( function() {
var loadTabOrder = function(id){
// Define friendly data store name
var dataStore = window.sessionStorage;
var oldIndex = 0;
// Start magic!
try {
// getter: Fetch previous value
oldIndex = dataStore.getItem(id);
} catch(e) {}
return oldIndex;
};
var saveTabOrder = function(id, currentIndex){
// Define friendly data store name
var dataStore = window.sessionStorage;
// Start magic!
try {
dataStore.setItem( id, currentIndex );
} catch(e) {}
};
$('.ui-tabs-vertical').each(function(){
var id = $(this).prop('id');
if(!id) $.error('.ui-tabs-vertical requires an id');
var element = $( "#"+id );
var options = {
active: loadTabOrder(id),
activate: function(event, ui) {
saveTabOrder(id, ui.newTab.parent().children().index(ui.newTab));
}
};
element.tabs(options).addClass( "ui-helper-clearfix" );
var nav = element.find('> .ui-tabs-nav > li');
nav.removeClass( "ui-corner-top" ).addClass( "ui-corner-left" );
var height = 0;
nav.each(function(){
height += $(this).outerHeight();
});
element.find('> .ui-tabs-panel').css(
'min-height',
height+'px'
);
});
} );
} ) ( jQuery, window, document );
Somewhere in your theme/pllugin put this:
//ui css
wp_enqueue_style('jquery-ui');
//jquery
wp_enqueue_script('jquery');
//jquery-ui
wp_enqueue_script('jquery-ui');
//you only need to do the above it you dont have them included already
//add our JS page.
wp_enqueue_script('mytabs', plugin_dir_url(__FILE__).'mytabs.php', ['juery-ui']);
//in my case this is in a plugin file, obviously use your path to your JS file
In your CSS file add these, make sure your CSS loads after jQuery UI
.ui-tabs.ui-tabs-vertical {
padding: 0;
height: 100%;
width: calc(100% - 15px);
position: relative;
}
.ui-tabs.ui-tabs-vertical .ui-widget-header {
border: none;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav {
float: left;
width: 10em;
background: #EEE;
border-radius: 4px 0 0 4px;
border-right: 1px solid gray;
position: absolute;
top : 0;
bottom: 0;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li {
clear: left;
width: 100%;
margin: 0.2em 0;
border: 1px solid gray;
border-width: 1px 0 1px 1px;
border-radius: 4px 0 0 4px;
overflow: hidden;
position: relative;
right: -2px;
z-index: 2;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li a {
display: block;
width: 100%;
padding: 0.6em 1em;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li a:hover {
cursor: pointer;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active {
margin-bottom: 0.2em;
padding-bottom: 0;
border-right: 1px solid white;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li:last-child {
margin-bottom: 10px;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-panel {
float: left;
margin-left: 150px;
width: calc(100% - 200px);
min-width: 600px;
border-radius: 0;
position: relative;
left: -1px;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-panel .panel-title{
padding: 0px;
margin: 0px;
margin-bottom: 10px;
font-size: 22px;
}
In your HTML add something like this
<div id="myttabs" class="ui-tabs-vertical">
<ul>
<li>General</li>
<li>Foo</li>
</ul>
<div id="settings-panel">
<p>Here is some settings</p>
</div>
<div id="foo-panel">
<p>Here is some foo</p>
</div>
</div>
Overview
How it works. In the above HTML you will notice ui-tabs-vertical class. Then in our mytabs.js we do this:
$('.ui-tabs-vertical').each(function(){ ... }
In short what this does is any element that has the ui-tabs-vertical class will get the ui-tabs added automagially. This is especially nice for wordpress as we can get into a real mess trying to put JS in a post (for example). So we want it as clean an free as possible. This trick with some variation can be used on any of the UI elements that create similar stuff, same type of popup, or anything we can normalize to a common format, so we don't have too many arguments.
Pass options -via- data attributes
One way to pass options to the JS, that I didn't need here is to simply put them in a data- attribute on the main element or any element that makes sense. For example you can set .tabs({hide:true}) to hide the tabs.
So if I wanted to do that I would do something like this:
//in our HTML add the data attribute to the main element
<div id="myttabs" class="ui-tabs-vertical" data-hide="true" >
//in myscript.js - change the options object.
var element = $( "#"+id )
var options = {
hide: element.data('hide') | false,
active: loadTabOrder(id),
activate: function(event, ui) {
window.saveTabOrder(id, ui.newTab.parent().children().index(ui.newTab));
}
};
The active tag will be remembered by the users browser by making use of some simple Session Storage stuff in there. These are keyed off the ID of the main HTML element for the tabs. This makes that ID required, so there is a bit of code to issue an error to the console, for development purposes. Its important to use the tabs ID, because that way each tab will have it's own settings remembered. If we mixed them we would probably get some errors for missing tab indexes etc..
There are also some modifications to the vertical CSS to expand the area behind the Tabs. I probably spent the most time on this piece and its a relatively minor visual issue. But I cant have that in my work. This is actually quite tricky to do, as you will see below. It looks way better with the full width background.
You can see this issue even on the jQuery example page.
The way I fixed it was
position:absolute on the navigation box with a top:0 and bottom:0, the parent element should be position:relative. This alone basally solves the 100% height issue, now we have to deal with the side effects of absolute positioning.
A few tricks like this width: calc(100% - 200px); to dynamically get the width set up. Absolute elements are not part of the Box Model of the DOM, so it's very hard to account for them with just CSS as they don't hold any space in the container.
Now all we need to do is set the min-height. The only reason we need to do this is everything goes janky if you have a lot of menu item (absolute) but no content in the tab (height is smaller then the nav). Which will bust it out of the bottom of the ui-tabs container because its absolute positioned. This is because with the top:0 and bottom:0 we are tying the width of the navigation menu to the main ui-tabs container. When the panel is empty that container will be shorter then the menu, which is a problem with many menu items and tiny panels. It can also cause some issues if you load content -via- AJAX, as you may see this error for second while the request goes.
4 So with the last bit of JS we just need to set min-height to apx the same height as the navigation's height. Because the navigation is absolute and tied to the parent container (as I said above, its height is dependent on .ui-tabs), so we can't simply get the height of that. The only option I saw was to sum the height of it's contents, the li elements themselves. This is a bit harder but we only need to do it one time for each ui-tabs.
The absolute position stuff will dynamically adjust the height (with just CSS) if the tab height changes, such as loading content via AJAX or other dynamic stuff.
The .ui-tabs-panel are set to float:left with a margin apx the width of the tab navigation. This accounts for the horizontal space the navigation takes up. Then to get something resembling a proper 100% width, we can use width: calc(100% - 200px); again because the nav is absolute we are sort of stuck manually offsetting for it. So This has 150px for the menus width offset, (or the left-margin on the panel, about the same width as the nav) and an extra 50 for things like the margin on the right and some other padding etc. We could have used negative margins for some of these (but I didn't think about that tell now)
Now having the panel width dynamic and like a real 100% width, all we need to do to make the panel smaller is adjust the width of the container around the main UI-Tabs element. This way we can adjust it without sending any arguments to .tabs() or changing any thing with JS.
As I said that menu thing is a hard problem to solve, this is mainly due to the fact were limited in what we can do structure wise, or we will just break the ui-tabs. So we cant really change that, and that leave only JS and CSS. CSS is preferable because then we don't have to write yet more JS, and we would need to keep watch on the contents changing to resize it. Even then there would be some lag in the change. For example using an setInterval to keep an eye on it, this is something we want to avoid as it can affect performance too, and is more of a headache then the minor visual problem that this is.
Summery
I basically just pasted this from my own plugin, so I can't grantee that I covered everything. I cant stand little quirky things like the images above so I always fix that stuff. And I try to make my life easier later so now we just make the HTML and add the ui-tabs-vertical and mytabs.js takes care of the rest. Lastly we should never have to mess with mytabs.js and anytime we want a tab setup we just add the HTML with that class.
There is probably a tiny performance penalty to this (maybe) but in Wordpress it can be really hard to call JS from posts or other content in a "clean" way. So this just encapsulates all that code and make it a lot cleaner and easier to maintain IMO because, you are not mixing HTML and JS and CSS etc.
Hope it helps:
PS if the way I start my JS looks funny please see this question:
What advantages does using (function(window, document, undefined) { ... })(window, document) confer?
And this one:
How does this JavaScript/JQuery Syntax work: (function( window, undefined ) { })(window)?
Basically its a self executing function that keeps our global JS space clean, so we don't get any conflicts from other plugins, or scripts that may use the same variable names as we are.
I do a fair amount of plugin development, so its a bit more common to use it for that, but I just basically copy and paste it now, so... Also I feel I should mention this is part of a much larger script that dynamically adds a bunch of UI stuff for me. That way when I'm working on HTML, I can just work on HTML etc...
For the final result check this out:
;( function( $, window, document, undefined ) {
"use strict";
$( document ).ready( function() {
var loadTabOrder = function(id){
/*// Define friendly data store name
var dataStore = window.sessionStorage;
var oldIndex = 0;
// Start magic!
try {
// getter: Fetch previous value
oldIndex = dataStore.getItem(id);
} catch(e) {}
return oldIndex;*/
};
var saveTabOrder = function(id, currentIndex){
/*// Define friendly data store name
var dataStore = window.sessionStorage;
// Start magic!
try {
dataStore.setItem( id, currentIndex );
} catch(e) {}*/
};
$('.ui-tabs-vertical').each(function(){
var id = $(this).prop('id');
if(!id) $.error('.ui-tabs-vertical requires an id');
var element = $( "#"+id );
var options = {
active: loadTabOrder(id),
activate: function(event, ui) {
saveTabOrder(id, ui.newTab.parent().children().index(ui.newTab));
}
};
element.tabs(options).addClass( "ui-helper-clearfix" );
var nav = element.find('> .ui-tabs-nav > li');
nav.removeClass( "ui-corner-top" ).addClass( "ui-corner-left" );
var height = 0;
nav.each(function(){
height += $(this).outerHeight();
});
element.find('> .ui-tabs-panel').css(
'min-height',
height+'px'
);
});
$('#expand').click(function(){
$('#'+$( "#mytabs li.ui-tabs-active" ).attr('aria-controls')+' p').css({"height":'300px'});
});
$('#shrink').click(function(){
$('#'+$( "#mytabs li.ui-tabs-active" ).attr('aria-controls')+' p').css({"height":''});
});
} );
} ) ( jQuery, window, document );
.ui-tabs.ui-tabs-vertical {
padding: 0;
height: 100%;
width: calc(100% - 15px);
position: relative;
}
.ui-tabs.ui-tabs-vertical .ui-widget-header {
border: none;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav {
float: left;
width: 10em;
background: #EEE;
border-radius: 4px 0 0 4px;
border-right: 1px solid gray;
position: absolute;
top : 0;
bottom: 0;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li {
clear: left;
width: 100%;
margin: 0.2em 0;
border: 1px solid gray;
border-width: 1px 0 1px 1px;
border-radius: 4px 0 0 4px;
overflow: hidden;
position: relative;
right: -2px;
z-index: 2;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li a {
display: block;
width: 100%;
padding: 0.6em 1em;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li a:hover {
cursor: pointer;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active {
margin-bottom: 0.2em;
padding-bottom: 0;
border-right: 1px solid white;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-nav li:last-child {
margin-bottom: 10px;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-panel {
float: left;
margin-left: 150px;
width: calc(100% - 200px);
min-width: 600px;
border-radius: 0;
position: relative;
left: -1px;
}
.ui-tabs.ui-tabs-vertical .ui-tabs-panel .panel-title{
padding: 0px;
margin: 0px;
margin-bottom: 10px;
font-size: 22px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<div id="mytabs" class="ui-tabs-vertical">
<ul>
<li>General</li>
<li>Foo</li>
</ul>
<div id="settings-panel">
<p>Here is some settings</p>
</div>
<div id="foo-panel">
<p>Here is some foo</p>
</div>
</div>
<div style="margin-top: 20px">
<button id="expand" >Click here to expand the panel</button>
<button id="shrink" >Click here to shrink the panel</button>
</div>
The only notes here, is I added the buttons to showcase how the gray nav background resizes automatically and Stack Overflow wont let me use the sessionStorge here. So I had no choice but to comment it out.
Sense there is so much code, most of it is pretty simple stuff really, I didn't want it all in the snip-it windows, as its a bit harder to read there. So forgive the lengthy post, but I wanted it to all make sense.
Enjoy!
Related
I have a ticker-tape run of text but I would like to change the duration of the duration depending on the amount of text to be shown. When the amount is small, the text runs slowly which is fine but with a lot of text, the tape whizzes by.
.marquee {
/* margin-left: auto;
margin-right: auto; */
width: 800px;
height: 25px;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
border: 1px solid #FF0000;
background: GhostWhite;
color: black;
font-size: 20px;
}
.marquee span {
display: inline-block;
padding-left: 100%;
animation: marquee 20s linear infinite;
}
/* Make it move */
#keyframes marquee {
0% { transform: translate(0, 0); }
100% { transform: translate(-100%, 0); }
}
In the html, I am running the span as follows:
<p class="marquee"><span><?php echo getEvents(); ?></span></p>
getEvents() is a php function that populates the ticker; from this I'd like to determine the length of text to throttle the speed of the text
It is the 20s in animation directive that says how much time the text has to move across its container. Short text will move slowly to cover the distance in 20 seconds. Much longer text will have to move much faster.
See this JSfiddle: https://jsfiddle.net/s40e3Lng/2/
The following JS/jquery sets the time to cross the <p> to a formula based on length of of the string inside the .
$('p.marquee span').each(function() {
var len = $(this).html().length;
var speed = 100;
var time = 4 + (4*len)/speed;
$(this).attr('style', 'animation: marquee '+time+'s linear infinite;');
});
In the JSfiddle, you can play around with the formula until you get a speed you like. Just change the JS code and click "Run" in top-left.
if you change your html so that
<p class="marquee" id="mID">
you could then use javascript to manipulate the elements of your
document.getElementById("mID").style.WebkitTransitionDuration = "1s"; // Code for Safari 3.1 to 6.0
document.getElementById("mID").style.transitionDuration = "1s";
I have these two styles that position my div in the footer of my page. What happens is that when you generate the content of the page for php, these div can override the content.
div.panel-foot {
position: absolute;
z-index: 2;
height: 30px;
width: 100%;
bottom: 0;
color: white;
background-color: #333333;
white-space: nowrap;
padding: 5px 100px;
}
div.panel-foot-information {
background-color: rgb(65, 65, 65);
position: absolute;
bottom: 30px;
max-width: none !important;
z-index: 1;
color: white;
font-size: small;
padding-top: 10px;
padding-bottom: 10px;
}
So what I do is when the content is small they stay on radapé ie with position: absolute, and when the content is longer they stay position: relative.
Anyone know a solution to resize content dynamically?
Unlike the other answers so far, I'm going to assume you have images and other things that a real website has, besides text.
I suggest using Javascript (since you've got a jQuery tag). PHP ultimately has no idea how much space the content will take up in the browser, so JS is your best option.
Have a look at my example here. If you remove some of the div content, you will see the footer color changes (because it changes the classname). all you have to do is plug in your own selectors and classnames and you're good to go.
// check the size of your conent div
// assuming it's got an id of "content"
contentHeight = $("#content").height();
// set the threshold that will determine how big is too big
threshold = 300;
// or if you want to make the threshold as big as the window...
// threshold = $(window).height();
// if the content height is greater than the threshold..
if(contentHeight > threshold){
// remove one class and add another
$("#footer").removeClass('green');
$("#footer").addClass('red');
}
// otherwise, do the opposite
else{
$("#footer").removeClass('red');
$("#footer").addClass('green');
}
I am using a bunch of divs (created with PHP) to generate a block of clickable elements. What I need to do is apply some styles to these generic elements, rather than to specific ones, yet using the code below seems to be invalid.
#Container {
height: 80%;
width: 60%;
background-color: green;
}
#Container div:hover {
background-color: blue;
}
<div id="Container">
<div style="background-color: red; width: 100px; height: 100px;">
</div>
http://jsfiddle.net/XD2eZ/
So I am not sure if it is an issue that a generic div element cannot be styled as a sub-element AND have a :hover attribute that operates properly. I know that classes or id's can be specified to handle this, but have thousands of unique divs. I also cannot use
#Container:hover div{ background-color: blue;}
As it ALSO seems to be invalid, but I need to select the one element from a block, and not all at once.
Any ideas here? Thanks in advance.
This will work if you remove the background color from the HTML, and apply it using css:
#Container {
height: 80%;
width: 60%;
background-color: green;
}
#Container div {background-color: red;}
#Container div:hover {
background-color: blue;
}
Example: http://jsfiddle.net/XD2eZ/1/
The reasone is CSS Specificity - a style attribute rule is much more specific (stronger) than an ID + element rule.
Sorry if this question has been asked a lot. I am currently working on a site that will have a custom gallery. Of all things to get stuck on right now, its the gallery page indicator.
On this page, the left portion will be made of a gallery of "galleries", displaying 6 galleries per "page". http://www.ct-social.com/ctsdev/aff/news-and-events/
Above the gallery are small blue dots that will serve as gallery indicators. The code to create the gallery indicators is as follows:
<?php for ($i=0; $i < $n2; $i++): ?>
<div class="event-gallery-unselected"></div>
<?php endfor; ?>
Upon loading I would like the left most dot to be given a different style that is attributed to class="event-gallery-selected". Upon clicking any other dot (except the current selection) the currently selected dot needs to revert back to "event-gallery-unselected" and the clicked dot takes on "event-gallery-selected"
I am kinda new to PHP, very new to JavaScript and JQuery. If using either of those languages as an example could you please breakdown your explanation? Thank you very much for all of your help.
Updated code:
CSS
.event-gallery.selected {
position: relative;
top: -0.7em;
background: white;
background-color: #1e93bb;
width: 20px;
height: 20px;
margin: 7px;
border-radius: 50%;
}
.event-gallery {
position: relative;
top: -1.1em;
background: white;
background-color: #63c5e7;
width: 15px;
height: 15px;
border-radius: 50%;
margin: 7px;
float: right;
cursor: pointer;
}
Updated Code JS
<script type="text/javascript">
jQuery(document).ready(function($){
$(".event-gallery").click(function() {
$(this).addClass('selected').siblings().removeClass('selected');
});
});
</script>
Just got it working now.
I would suggest having a class which is present on all of your gallery div elements. This will allow the common styles to be maintained and also allow you to have only 1 click handler. You can then have a separate selected class which you toggle as needed. Try this:
<?php for ($i = 0; $i < $n2; $i++): ?>
<div class="event-gallery"></div>
<?php endfor; ?>
.event-gallery {
color: #000; /* default styling ... */
padding: 5px;
}
.event-gallery.selected {
color: #FFF; /* selected item styling ... */
background-color: #C00;
}
$(".event-gallery").click(function() {
$(this).addClass('selected').siblings().removeClass('selected');
});
Example fiddle
use jQuery like this:
$('divid').click(function(){
$('divid').css('background-image', 'pic2.jpeg');
});
for example
If you have a set of elements:
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I typically handle it as such:
var $items = $('#wrapper .item');
$('.item').click(function(){
$items.removeClass('active'); // 'reset' the active links
$(this).addClass('active'); // apply the active class to the clicked item
})
This can easily be done with a little bit of help from jQuery.
$(function() {
$(".even-gallery-unselected").on("click", function() {
this.removeClass("event-gallery-unselected")
.addClass("event-gallery-selected");
});
});
I have a "news" div and a "banner" div.
I want user to see the "banner" div when page loads. This "banner" div should show over the "news" div, exactly over the position, covering the "news" div. So:
How should I do to detect position of "news" div and show the "banner" div over, floating, without affecting the grid structure?
Any jQuery plugin that allows user to hide that div and never show again? w/ cookie?
Hope you've understood my idea. I leave an image:
use the jquery's offset
http://api.jquery.com/offset/
and the jquery's show and hide
http://api.jquery.com/show/
you can use hte negative margin for the banner to come over to the news...div.
Let me know if you need anything...
use absolute postioning for news banner.
I've written a script for you which should help.
It uses the Cookie plugin for jQuery.
I've put some comments in the code so hopefully it should be pretty self-explanatory.
Feel free to come back with other questions you may have.
Usage
You should see a banner on first load, then click run again and it should dissapear.
The banner will be positioned exactly above the news-list using absolute positioning, the width/height and the top/left offset of the newslist.
I realise this question has already been answered, but I thought I'd offer a slight alternative, using CSS, jQuery and the jQuery cookie plugin:
html:
<div class="container">
<div class="news">
<p>Lorem ipsum dolor sit amet...</p>
</div>
<div class="banner">
<p>Yet more text, this time it's the banner.</p>
<span class="close">X</span>
</div>
</div>
<div id="clear">Remove the cookie</div>
css:
.container {
width: 80%;
min-height: 400px;
position: relative;
border: 4px solid #000;
}
.news {
width: 100%;
height: 100%;
}
.banner {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #f00;
}
.close {
position: absolute;
top: 0;
right: 0;
border-left: 2px solid #fff;
border-bottom: 2px solid #fff;
width: 2em;
line-height: 2em;
text-align: center;
display: block;
cursor: pointer;
}
#clear {
width: 80%;
text-align: right;
color: #fff;
background-color: #999;
border: 4px solid #000;
border-top-width: 0;
font-family: arial, sans-serif;
cursor: pointer;
}
jQuery:
$(document).ready(
function(){
if ($.cookie('closed')){
$('.banner').remove();
}
$('.close').click(
function(){
$(this).closest('.banner').remove();
$.cookie('closed',true, {expires: 30});
});
$('#clear').click(
function(){
$.cookie('closed',false, {expires: -200});
});
});
JS Fiddle demo.
A slightly more pleasing demo, with animate():
$(document).ready(
function(){
if ($.cookie('closed')){
$('.banner').remove();
}
$('.close').click(
function(){
$(this)
.closest('.banner')
.animate(
{
'top':'120%'
}, 1500,
function(){
$(this).remove();
}
);
$.cookie('closed',true, {expires: 30});
});
$('#clear').click(
function(){
$.cookie('closed',false, {expires: -200});
});
});
Demo at JS Fiddle
Edited with an afterthought, assuming that you get repeat visitors, it might be worth re-setting the cookie in the initial if check, to ensure that they don't see the banner ever again (unless they leave more than 30 days between visits), changing it to:
if ($.cookie('closed')){
$('.banner').remove();
$.cookie('closed',true,{expires: 30});
}