Why is this thing not working? If I remove ::before from javascript and css it works. But due to the design needs there has to be a ::before. How do I point to the class + ::before?
$(function () {
var sections = $("section");
var navigation_links = $("nav a");
sections.waypoint({
handler: function (event, direction) {
var active_section;
active_section = $(this);
if (direction === "up") active_section = active_section.prev();
var active_link = $('nav a[href="#' + active_section.attr("id") + '"]');
navigation_links.removeClass("selected::before");
active_link.addClass("selected::before");
},
offset: '25%'
})
});
css:
.selected::before {
display: block;
content: "";
margin-top: 6px;
width: 8px;
height: 8px;
background: url(../img/sprite.png) -126px -196px;
background-size: 400px 480px;
float: left;
margin-left: 20px;
margin-right: 20px;
}
You don't need to add the ::before in the JS. As long as the .selected class appears on the element, CSS will do the rest. addClass("selected::before") is telling the browser to add a class called "selected::before", which is not what you want. (I'm not even sure you are allowed to have :: in a class name, but I suspect not.)
Related
I have some quantity inputs. I want to collect the data in "inputs" and show them in "#yolcudropdown". But I just can't pull the data. Inputs must be disabled. There should be no manual entry. I did something at the bottom of the "javascript" section. But I couldn't run it.
(function( $ ) {
$.fn.number = function(customOptions) {
var options = {
'containerClass' : 'number-style',
'minus' : 'number-minus',
'plus' : 'number-plus',
'containerTag' : 'div',
'btnTag' : 'span'
};
options = $.extend(true, options, customOptions);
var input = this;
input.wrap('<' + options.containerTag + ' class="' + options.containerClass + '">');
var wrapper = input.parent();
wrapper.prepend('<' + options.btnTag + ' class="' + options.minus + '"></' + options.btnTag + '>');
var minus = wrapper.find('.' + options.minus);
wrapper.append('<' + options.btnTag + ' class="' + options.plus + '"></' + options.btnTag + '>');
var plus = wrapper.find('.' + options.plus);
var min = input.attr('min');
var max = input.attr('max');
if(input.attr('step')){
var step = +input.attr('step');
} else {
var step = 1;
}
if(+input.val() <= +min){
minus.addClass('disabled');
}
if(+input.val() >= +max){
plus.addClass('disabled');
}
minus.click(function () {
var input = $(this).parent().find('input');
var value = input.val();
if(+value > +min){
input.val(+value - step);
if(+input.val() === +min){
input.prev('.' + options.minus).addClass('disabled');
}
if(input.next('.' + options.plus).hasClass('disabled')){
input.next('.' + options.plus).removeClass('disabled')
}
} else if(!min){
input.val(+value - step);
}
});
plus.click(function () {
var input = $(this).parent().find('input');
var value = input.val();
if(+value < +max){
input.val(+value + step);
if(+input.val() === +max){
input.next('.' + options.plus).addClass('disabled');
}
if(input.prev('.' + options.minus).hasClass('disabled')){
input.prev('.' + options.minus).removeClass('disabled')
}
} else if(!max){
input.val(+value + step);
}
});
};
})(jQuery);
$('.quntity-input').each(function () {
$(this).number();
});
/* THIS IS IMPORTANT */
$(document).ready(function() {
$(document).on('change', '.btw', function() {
$('#yolcudropdown').text($(this).val());
});
});
.number-style {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-pack: start !important;
justify-content: flex-start !important;
-ms-flex-align: center !important;
align-items: center !important;
}
.number-style .number-minus,
.number-style .number-plus {
height: 28px;
background: #ffffff;
border: 2px solid #e2e2e2 !important;
width: 28px;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
-ms-border-radius: 100%;
border-radius: 100%;
line-height: 23px;
font-size: 19px;
font-weight: 700;
text-align: Center;
border: none;
display: block;
cursor: pointer;
}
.number-style .number-minus:active,
.number-style .number-plus:active {
background: #e2e2e2;
}
.number-style .number-minus {
line-height: 20px;
}
.number-style .number-minus::after {
content: "-";
font-size: 10px;
}
.number-style .number-plus {
line-height: 18px;
}
.number-style .number-plus::after {
content: "+";
font-size: 10px;
}
.number-style .quntity-input {
width: 28px;
background: #e00f23;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
-ms-border-radius: 100%;
border-radius: 100%;
line-height: 21px;
font-size: 14px;
color: #ffffff;
font-weight: 700;
text-align: Center;
margin: 0 5px;
display: block;
cursor: pointer;
text-align: center;
border: none;
height: 28px;
font-weight: 600;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="quntity-input btw" type="text" value="0" step="1" min="0" max="10">
<input class="quntity-input btw" type="text" value="0" step="1" min="0" max="10">
<div id="yolcudropdown">İnput quantity show this div</div>
"class" names of "input" elements are the same. I need to collect inputs with the same value and display them in the div instantly
HTMLInputElement
Input type "text" has no min max or step attributes, so your HTML is absolutely invalid. Try not to write It-works, I'm a framework -code. Respect the W3C standards.
Use type="number" (CSS pseudos can help you remove default spinner arrows from such elements)
Also step could be floats. Respect that and use parseFloat() in JS
CSS Flex to align stuff
Seems you know about CSS-flex, use it! Height, therefore- line-height... 19? 20? 23px? No. Just use flex.
CSS !important
!important is sign of poor coding style and should be left to Bootstrap only. Or to hopefully override Bootstrap styles - or in that cases when developers actually know what they are doing.
jQuery Plugins
jQuery plugins, I suggest to read the DOCS and get a deeper knowledge on how plugins work. Almost every jQuery method is a plugin. .hide() , .addClass()... I won't count them all. Plugins are chainable .removeClass("foo").stop().fadeTo(1), and so should be your .number() plugin.
To achieve chain-ability you simply return the bound this. PS: that's not jQuery... that's how JS works.
jQuery Plugins are not meant to be called inside a $.each() loop. $() is already a collection of DOM Nodes wrapped in a jQuery Object. No need to .each(). Same like: you would rather use $('a').css({color:'blue'}) instead of $('a').each(){ $(this).css({color: 'blue'}); });. Same effect, less code. Plugins.
jQuery DOM ready
jQuery(function($) { }); // DOM ready and $ alias in scope
Or if you don't care about ±IE, or you use ES6 syntax and a toolchain like Babel than: jQuery($ => { }) will suffice.
jQuery $ Object Constructor
jQuery allows you to define an HTMLElement that will eventually become a new DOM element wrapped with all the jQuery powers, Methods. Meaning that, if instead of passing a selector, you pass a more complex Tag-alike string (say: $("<span/>", {}); - jQuery will create an inMemory SPAN element and allow you to use the second parameter {} for most of the available jQuery Methods for that $Element. Let's use this!
jQuery plugin callbacks
If you want to provide a callback after a user changes the input value, provide a callback method. Don't force a programmer to write new spaghetti code, stick to the scope of your available Plugin internal Methods.
Sum Elements values
To sum Elements values you can use Array.prototype.reduce, just make sure to use an initialValue to prevent possible TypeErrors.
Example
Finally, here's the simplified CSS and improved JS:
(function($) {
$.fn.number = function(customOptions) {
const options = $.extend(true, {
containerTag: "div",
containerClass: "number-style",
minusClass: "number-minus", // consistency in wording!
minusText: "-", // Give power to the user!
plusClass: "number-plus",
plusText: "+",
btnTag: "button",
onChange() {}, // Provide a nifty callback!
}, customOptions);
this.each(function() { // Use .each() here!
const $input = $(this);
let val = parseFloat($input.value || 0); // floats!
const min = parseFloat($input.attr("min"));
const max = parseFloat($input.attr("max"));
const step = parseFloat($input.is("[step]") ? $input.attr("step") : 1);
const handleStyles = () => {
$minus.toggleClass('disabled', val <= min);
$plus.toggleClass('disabled', val >= max);
};
const change = () => {
val = Math.max(min, Math.min(max, val)); // Keep val in range.
$input.val(val); // Update input value
handleStyles(); // Update styles
options.onChange.call($input[0], val); // Trigger a public callback
}
const decrement = () => {
val -= step;
change();
};
const increment = () => {
val += step;
change();
};
const $minus = $(`<${options.btnTag}>`, {
type: "button",
title: "Decrement",
class: options.minusClass,
text: options.minusText,
on: {
click: decrement
}
});
const $plus = $(`<${options.btnTag}>`, {
class: options.plusClass,
title: "Increment",
text: options.plusText,
on: {
click: increment
}
});
const $wrapper = $(`<${options.containerTag}>`, {
class: options.containerClass,
});
$input.after($wrapper);
$wrapper.append($minus, $input.detach(), $plus); // Append all
handleStyles(); // handle initial styles
});
return this; // make your plugin chainable!
};
})(jQuery);
jQuery(function($) { // DOM ready and $ alias in scope
const $quantityInp = $('.quantity-input'); // Cache your elements!
const $dropdown = $('#yolcudropdown'); // Cache your elements!
$quantityInp.number({
onChange(val) { // our custom onChange callback!
const tot = $quantityInp.get().reduce((acc, el) => {
acc += parseFloat(el.value);
return acc;
}, 0);
$dropdown.text(tot);
}
});
});
/* QuickReset */ * { margin:0; box-sizing:border-box; }
.number-style input::-webkit-outer-spin-button,
.number-style input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.number-style {
display: flex;
}
.number-style > * {
height: 2em;
min-width: 2em;
border-radius: 2em;
display: flex; /* Use flex. */
justify-content: center;
text-align: center;
border: 0;
background: #ddd;
}
.number-style button {
background: #fff;
box-shadow: inset 0 0 0 2px #ccc;
cursor: pointer;
user-select: none;
/* no highlight, please! */
}
.number-style button:active {
background: #0bf;
}
.number-style input {
background: #e00f23;
color: #fff;
margin: 0 5px;
}
.number-style .disabled {
opacity: 0.2;
cursor: default;
}
/* Custom overrides: */
.number-style>* {
width: 2em;
/* just for roundness */
}
<input class="quantity-input" type="number" value="0" step="1" min="0" max="10">
<input class="quantity-input" type="number" value="0" step="1" min="0" max="10">
<div id="yolcudropdown">0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Additional reading:
HTMLInputElement
Math/min
Math/max
jQuery plugin-creation
$ new-elements
Array/reduce
jQuery.toggleClass()
And PS: it's "quantity", not "quntity"
My issue is that when i append 2 divs white jQuery, there names are:
This is div 1
This is div 2
But when i remove the first div (This is div 1)
and append another div
it adds one more div whit name (This is div 2):
This is div 2
This is div 2
The reason is because the name of the div counts the total amout of divs... Is there any other way to number all divs so they will always be like this:
This is div 1
This is div 2
This is div 3
Even if i the divs are:
This is div 1
This is div 6
This is div 12
I want them always to be 1,2,3
jQuery code:
$('#add_item').click(function() {
//div count
var countDivs = $("div").length;
//append content
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div '+countDivs+'</h2>')
var appendContent = ('<div>'+h2+removeBtn+'</div>')
$('#accordion').append(appendContent);
});
//remove button
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
return false;
});
JSFIDDLE
I think you'll have to edit contents of the divs each time a div is removed.
Let's say you have an element and you want to add divs to it.
You will add like you are right now and when you remove you edit all other divs.
The code would be something like this
$('#add_item').click(function() {
var countDivs = $("div").length;
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div '+countDivs+'</h2>')
var appendContent = ('<div class="appDiv">'+h2+removeBtn+'</div>')
$('#accordion').append(appendContent);
});
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
$('.appDiv').each(function(index,el){
$(el).find('h2').text('This is div '+(index+1));
});
return false;
});
here is the Fiddle
Hope this helps :)
Write a function to renaming the divs and call it after append/remove.
function reArrange() {
$("#accordion > div").each(function(i) {
$(this).find("h2").text("This is div" + (i + 1))
});
}
Fiddle
When an item is removed, change the title of all the elements after it.
$('#add_item').click(function() {
var countDivs = $("#accordion div").length + 1;
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div <span>' + countDivs + '</span></h2>')
var appendContent = ('<div>' + h2 + removeBtn + '</div>')
$('#accordion').append(appendContent);
});
$(document).on('click', '.removeBtn', function() {
var $div = $(this).parent();
$div.nextAll('div').find('span').html(function(i, html) {
return --html
});
$div.remove();
return false;
});
div {
position: relative;
}
#accordion {
margin-left: 60px;
padding: 10px;
background: #ddd;
}
#add_item {
position: absolute;
top: 20px;
left: 20px;
font-size: 20px;
padding: 5px 10px;
background: black;
color: white;
cursor: pointer;
}
.removeBtn {
font-size: 20px;
padding: 2px 10px 5px;
background: black;
color: white;
cursor: pointer;
position: absolute;
top: 0px;
font-family: verdana;
border-radius: 100%;
left: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="accordion">
</div>
<a id="add_item">+</a>
you should use a global variable like "count":
var count=1;
$('#add_item').click(function() {
//div count
//var countDivs = $("div").length;
var countDivs =count;
//append content
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div '+countDivs+'</h2>')
var appendContent = ('<div>'+h2+removeBtn+'</div>')
$('#accordion').append(appendContent);
count++;
});
//remove button
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
return false;
});
The easiest update would be to trigger a recount (or other named-event) and, upon addition or removal of an element – by clicking either the #add_item or .removeBtn – call that function using the on() method to listen for that event.
In the below code we bind the event-listener to the #accordion element, as the closest ancestor present in the DOM on page load:
$('#add_item').click(function() {
var removeBtn = ('<a class="removeBtn">x</a>');
var h2 = ('<h2></h2>');
var appendContent = ('<div>'+h2+removeBtn+'</div>');
$('#accordion').append(appendContent).trigger('recount');
});
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
// triggering the 'recount' event from the
// #accordion:
$('#accordion').trigger('recount');
return false;
});
// listening for the 'recount' event:
$('#accordion').on('recount', function(){
// looking within the #accordion for
// the <h2> elements (which contain the
// text to update), and using the text()
// method's anonymous function along with
// its i argument (the index of the current
// <h2> in the collection):
$(this).find('h2').text(function(i){
// returning the text string concatenated
// with the index plus 1 (to get a 1-based
// count, rather than JavaScript's 0-based):
return 'This is div ' + (i + 1);
});
});
$('#add_item').click(function() {
var removeBtn = ('<a class="removeBtn">x</a>');
var h2 = ('<h2></h2>');
var appendContent = ('<div>' + h2 + removeBtn + '</div>');
$('#accordion').append(appendContent).trigger('recount');
});
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
$('#accordion').trigger('recount');
return false;
});
$('#accordion').on('recount', function() {
$(this).find('h2').text(function(i) {
return 'This is div ' + (i + 1);
});
});
div {
position: relative;
}
#accordion {
margin-left: 60px;
padding: 10px;
background: #ddd;
}
#add_item {
position: absolute;
top: 20px;
left: 20px;
font-size: 20px;
padding: 5px 10px;
background: black;
color: white;
cursor: pointer;
}
.removeBtn {
font-size: 20px;
padding: 2px 10px 5px;
background: black;
color: white;
cursor: pointer;
position: absolute;
top: 0px;
font-family: verdana;
border-radius: 100%;
left: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="accordion">
</div>
<a id="add_item">+</a>
References:
on().
text().
trigger().
I'm trying to give my text a background colour, simple enough but I have come into some difficulty.
Here's my html
<div class="hero_text">Screen Shot</div>
I needed to break this apart so that if there was a space, then the next word go onto a new line.
Here's my jquery
jQuery(document).ready(function($) {
$('.hero_text').html(function(index, text) {
return text.replace(' ', '<br>');
});
});
Here's my css
.hero_text {
color: #FFF;
text-align: right;
background: green;
padding-left: 5px;
font-size: 30px;
display: inline;
float: right;
padding-right: 9px;
clear: both;
position: fixed;
right: 0;
bottom: 30%;
line-height: 30px;
}
Here's an image of what I'm getting at the moment
And here is what i'm trying to achieve
Notice the pink has got a little bit of padding to the left and right of the word but as the words are different length then the pink should be smaller and larger depending on the word?
Thanks
One approach, using jQuery to manipulate the HTML, is:
$('.hero_text').html(function (i,oldHTML){
return oldHTML.replace(/\b([a-zA-Z]+)\b/g,'<span>$1</span>');
});
Coupled with the additional CSS:
.hero_text span {
background-color: green;
float: right;
clear: right;
}
JS Fiddle demo.
http://jsfiddle.net/S6sfu/
This is one without java script, will this do?
HTML
<div class="hero_text">Screen</div>
<div class="hero_text">Shot</div>
<div class="hero_text">A quick message</div>
CSS
.hero_text {
color: #FFF;
text-align: right;
background: green;
padding-left: 5px;
font-size: 30px;
display: inline;
float: right;
padding-right: 9px;
clear: both;
right: 0;
bottom: 30%;
line-height: 30px;
}
You can split up the text into an array and than add the spans as you want. Somewhat like this:
jQuery(document).ready(function($) {
var textArray= $('.hero_text').html().split(' ');
$('.hero_text').html('<span style="background: green;">'+textArray[0]+'</span><br>'+'<span style="background: green;">'+textArray[1]+'</span>');
});
Check out the following url: http://css-tricks.com/multi-line-padded-text/
Nearly all possible methods are supplied there.
If you don't have access to the html you could move the contents of the div to a span:
(Which is a VERY bad idea to begin with)
var $node = $('.hero_text');
var text = $node.innerHtml();
var $span = $('<span class="hero_text"></span>');
$span.appendTo($node.parent());
$node.remove();
See if this helps. I have updated the javascript in your code.http://jsfiddle.net
var text_arr = $('.hero_text').text().split(' ');
$('.hero_text').html('');
for(i=0; i< text_arr.length; i++)
{
$('.hero_text').append('<span class="text'+i+' clearfix">'+ text_arr[i] +'</span>');
}
If you dont have access to div or the css ,
this is the solution you can consider :
UPDATED
jsfiddle : http://jsfiddle.net/P5LNx/7/
jQuery(document).ready(function ($) {
$('.hero_text').html(function (index, text) {
var bgcolor = $(this).css('background');
$(this).css('background', 'transparent');
var txt = text.split(' ');
var content = '<span style="background: ' + bgcolor + ';position:relative;">' + txt[0] + '</span><br>';
content += '<span style="background: ' + bgcolor + ';">' + txt[1] + '</span>';
return content;
});
});
Steps :
Removed background of the div.
Added 2 <span> with same background as div
To <span>s, added your words (1 in each)
I've been looking for a way to style a couple of <select> tags in a madlib-esque fashion.
I want the select box width to be based on what is selected and not show extra whitespace.
I'm looking for a way to make this as cross-browser compatible as possible right now it works fine in webkit but the dreaded arrows show in firefox.
Progressive enhancement JS only, fallback to regular select field.
Here is my fiddle: http://jsfiddle.net/bXJrk/
Any help on achieving this would be greatly appreciated.
$('select').each(function(){
var width = $('option[value='+$(this).val()+']').html();
$('body').append('<span id="'+$(this).val()+'" style="display:none">'+width+'</span>');
var two = $('#'+$(this).val()).width();
$(this).width(two+4).addClass('jsselect');
});
$('select').change(function(){
var width = $('option[value='+$(this).val()+']').html();
$('body').append('<span id="'+$(this).val()+'" style="display:none">'+width+'</span>');
var two = $('#'+$(this).val()).width();
$(this).width(two+4);
});
This is what I got out.
The fiddle: http://jsfiddle.net/wAs7M/4/
Javascript:
$('.replacementcontainer select').each(function(){
var apply = function(el){
var text = $('option[value='+el.val()+']').html();
var span;
if (el.data('initialized'))
{
span = el.parent().next().html(text);
}
else
{
el.data('initialized', true);
el.after('<span id="'+el.val()+'" class="jsselect hiddenspan">'+text+'</span>');
el.wrap($('<span class="selwrapper"></span>'));
span = el.parent().next();
span.addClass('jsselect');
el.addClass('jsselect');
}
el.parent().width(span.width() + 5);
var two = span.width();
};
apply($(this));
$(this).change(function(){ apply($(this)); });
});
CSS:
*{font-family:sans-serif;font-size:15px}
.replacementcontainer {
margin: 10px;
}
.replacementcontainer span {
display: inline-block;
margin-bottom: -4px;
}
.jsselect {
color: #3084CA;
text-decoration: underline;
border: none;
background: none;
padding: 0;
margin: 0;
cursor: pointer;
outline: none;
}
.selwrapper {
display: inline-block;
overflow: hidden;
}
.hiddenspan {
visibility:hidden;
position:absolute;
}
I have some problems converting the CSS id to a class and the javascript to match it. I need to use the script multiple times on the site
Here my code:
CSS:
#first {
background-color: #FFF;
width: auto;
height: auto;
overflow: hidden;
padding: 10px;
}
JavaScript:
var divh = document.getElementById('first').offsetHeight;
//keep default height
var divh = $("#first").outerHeight();
document.getElementById("first").style.height = "100px";
//toggle functions
$('div:first').toggle(
function () {
$("#first").stop().animate({
height: divh +'px'
}, 1000);
},
function () {
$("#first").stop().animate({
height: '100px'
}, 1000);
}
)
If I understand correctly you can just do:
.first {
background-color: #FFF;
width: auto;
height: auto;
overflow: hidden;
padding: 10px;
}
And the Javascript would be something like this:
var divh = $('.first').offsetHeight;
//keep default height
var divh = $(".first").outerHeight();
$('.first').style.height = "100px";
//toggle functions
$('div:first').toggle(
function () {
$(".first").stop().animate({
height: divh +'px'
}, 1000);
},
function () {
$(".first").stop().animate({
height: '100px'
}, 1000);
}
)
Just uses the jQuery selector to select the class instead of the ID.
I think you can use a "class selector" to get all the elements belonging to that class and then apply animation to all of them or one by one by using the each function (see here). Something like:
CSS
.first {
background-color: #FFF;
width: auto;
height: auto;
overflow: hidden;
padding: 10px;
}
JavaScript:
$('.first').each(function () {
var divh = $(this).outerHeight();
ecc. ecc.
})
use .first instant of #first
Mark's answer is almost entirely correct.
Although, he changed $('div:first') to $('div.first') which are not the same thing.
:first is part of jQuery selectors to select only the first matched element (see here).
So, if you want to pick the first div, use $('div:first'). If you want to select all divs with the "first" class, use $('div.first').