I am attempting to get a css value of a background. My attempt is failing and the correct value isn't being delivered. I have a spectrum.js color picker and no matter which color I choose rgba(0,0,0,0) is always chosen. When I look at the background in the console it displays it correctly in the DOM.
Does anybody see why this is failing?
<div class="container" id="outside-preview">
<div class="container" id="inside-preview">
<div id="image-square"></div>
</div>
</div>
$(".colorpicker").spectrum({
color: "#FFF",
showInput: true,
className: "full-spectrum",
showInitial: true,
showPalette: true,
showSelectionPalette: true,
maxSelectionSize: 10,
preferredFormat: "hex",
localStorageKey: "spectrum.demo",
change: function(color) {
var eq = $(this).index('.colorpicker');
$('.container').eq(eq).css('background-color', color.toHexString())
}
});
var color = $( "#outside-preview" ).css( "background-color" );
$("#result").html("That div is " + color + "");
Fiddle
You need to place the code which reads the CSS value in the change handler so that it updates the #result element after a selection is made. Your current code is only reading it on load.
change: function(color) {
var eq = $(this).index('.colorpicker');
$('.container').eq(eq).css('background-color', color.toHexString())
var color = $("#outside-preview").css("background-color");
$("#result").html("That div is " + color);
},
Updated fiddle
Related
Using the Color Thief javascript effect, I have written some code that grabs an images dominant color and adjusts the entire theme's color scheme based on the image.
This all works well on a single product page, where only one image is being used. On my catalog page, there are multiple images that I need to grab the dominant color from. One image for each product. I need to display each separate color along with the product.
You can see the colored border in each product's panel (it's a brown/orange color).
My very slimmed-down code I'm using is below:
jQuery( document ).ready( function( $ ) {
var image = new Image;
var bg;
$('.post-image-hidden-container').each(function() {
bg = $(this).text();
image.onload = function() {
var colorThief = new ColorThief();
var dominantColor = colorThief.getColor(image);
var colorPalette = colorThief.getPalette(image, 7);
var backgroundColor = 'rgb('+ dominantColor +')';
/* Calculate the Lightest Color in the Palette */
var lightestColor = colorPalette.reduce(function(previousValue, currentValue) {
var currLightNess = (0.2126*currentValue[0] + 0.7152*currentValue[1] + 0.0722*currentValue[2]);
var prevLightNess = (0.2126*previousValue[0] + 0.7152*previousValue[1] + 0.0722*previousValue[2]);
return (prevLightNess < currLightNess) ? currentValue : previousValue;
});
/* Calculate the Darkest Color in the Palette */
var darkestColor = colorPalette.reduce(function(previousValue, currentValue) {
var currLightNess = (0.2126*currentValue[0] + 0.7152*currentValue[1] + 0.0722*currentValue[2]);
var prevLightNess = (0.2126*previousValue[0] + 0.7152*previousValue[1] + 0.0722*previousValue[2]);
return (prevLightNess > currLightNess) ? currentValue : previousValue;
});
/* Create Shades and Tints of Lightest Color */
...
/* Shades (darker) */
...
/* Tints (lighter) */
...
/* Handle all CSS based on returned colors */
$('.product-bottom-info-container').each(function() {
$(this).css({
borderTop: '3px solid rgb('+ lightestColor +')'
});
});
}
image.src = bg;
});
});
Right after declaring the variable bg I wrapped the entire thing in an each() loop. Down towards the bottom, .product-bottom-info-container is the element where the colored border appears. I cannot seem to get each product's border to be it's own color. It keeps giving every border the LAST color in the loop.
Some notes:
.post-image-hidden-container is a hidden div above each product that contains the product's image url.
.product-bottom-info-container is the container at the bottom of each product with the product title and the colored border.
Am I using the each() function properly? What am I doing wrong?
Thanks
UPDATE
I was able to grab all of the RGB values for each image and put them into an array:
var thisColor;
var theseColors = [];
$('.shop-page-item-thumb').each(function() {
$(this).find('img').each(function() {
thisColor = colorThief.getColor(this);
theseColors.push(thisColor);
});
});
Now that I have all RGB's available, is there a way to simply loop through this array and assign each value to its respective .product-bottom-info-container element?
theseColors[0] is the first RGB, theseColors[1] is the second, etc. all the way up to theseColors[11].
If I run console.log(thisColor) inside of the loop, I get these results:
[29, 28, 22]
[217, 195, 189]
[14, 14, 8]
[233, 232, 206]
[31, 31, 31]
[82, 97, 111]
[60, 68, 84]
[34, 29, 30]
[17, 30, 37]
[12, 11, 12]
[56, 43, 26]
[209, 150, 108]
The 12 RGB values that I need. So we're headed in the right direction.
UPDATE for Mottie
Here is the HTML structure for one of the products. .shop-page-item-thumb is the container that holds the thumbnail, but .shop-page-item-article is the parent (besides the actual li list item).
FINAL UPDATE (Thanks Mottie!)
This is the piece of code that finally worked:
$('.shop-page-item-thumb').each(function() {
var thumb = $(this);
thumb.find('img').each(function() {
thisColor = colorThief.getColor(this);
thumb.parent().find('.product-bottom-info-container').css({
borderTop: '3px solid rgb('+ thisColor +')'
})
});
});
Much love, Stack Overflow! <3
It looks like this code is looping through each container after each image load...
/* Handle all CSS based on returned colors */
$('.product-bottom-info-container').each(function() {
$(this).css({
borderTop: '3px solid rgb('+ lightestColor +')'
});
});
try this instead:
$(this).closest('.product-bottom-info-container').css({
borderTop: '3px solid rgb('+ lightestColor +')'
});
Update: Oh sorry, I didn't look at the code that closely... another problem is the image definition. There is only one, not one for each container... Instead of defining it outside the loop, find it inside of the .each loop and then attach an onload...
$(this).find('img')[0].onload = function() {
It shouldn't change the above code that adds the border color since this would refer to the image inside of the onload function.
It would have been easier to troubleshoot the problem if you would have provided a ready-made demo to use.
Update2: Instead of pushing the colors to an array, apply them directly to the border; I have no idea about the thumb images in relation to the containers, so we're just going to assume that the thumbs are in the same order as the containers. Some HTML would have helped. Updated for the given HTML...
$('.shop-page-item-thumb').each(function() {
var thumb = $(this);
thumb.find('img').each(function() {
thisColor = colorThief.getColor(this);
// prev() targets the previous element (it should be
// the 'product-bottom-info-container'; or use
// thumb.parent().find('.product-bottom-info-container')
thumb.prev().css({
borderTop: '3px solid rgb('+ thisColor +')'
});
});
});
I'm trying to use Ion.RangeSlider to make a slider where the color starts from the center and goes in the direction of the slider control until it hits the slider control. Right now, this is what I have:
Instead, I would like the color to go from the center of the slider to the slider control.
How can I make the RangeSlider work like that so that the color starts from the middle (as shown above)?
EDIT:
I looked at this question, but it deals with sliders with two controls instead one.
EDIT 1:
setup.js:
jQuery(document).ready(function($){
$(".slider").each(function() {
console.log($(this).attr("id"));
$(this).ionRangeSlider({
type: $(this).attr("data-slider_type"),
grid: $(this).attr("data-slider_grid"),
min: $(this).attr("data-slider_min"),
max: $(this).attr("data-slider_max"),
prefix: $(this).attr("data-slider_prefix")+" ",
postfix: " " + $(this).attr("data-slider_suffix"),
step: $(this).attr("data-slider_stepper"),
from: $(this).attr("data-slider_from")
});
$(this).on("change", function () {
var $this = $(this),
value = $this.prop("value").split(";");
});
});
});
Use: https://github.com/jordansoltman/ion.rangeSlider with has the additional boolean option: fixMiddle. For example:
$(".slider").ionRangeSlider({
fixMiddle: true,
...
});
Note: use ion.rangeSlider.js as ion.rangeSlider.min.js has not been updated.
to all Javascript experts this question might be just basics. I'm using jQuery and I am working on a tooltip created with jQuery.flot.
The following is a part of my javascript function within an html file and this is exactly what I need to have the tooltip div to be rendered correctly:
$('<div id="tooltip">' + contents + '</div>').css( {
Because the div is not shown I used Firebug to look for the reason and the line of code from above shows the special characters < and > encoded as html entities < and > as you can see here:
$('<div id="tooltip">' + contents + '</div>').css( {
I was searching several online sources for a solution and tried things like .replace(/lt;/g,'<') or .html().text() and it took me more than three hours but nothing was helpful.
I works fine on localhost.
Full Source Code:
<script language="javascript" type="text/javascript" src="../JavaScript/flot/jquery.js"></script>
<script language="javascript" type="text/javascript" src="../JavaScript/flot/jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="../JavaScript/flot/jquery.flot.categories.js"></script>
<![CDATA[
<script type="text/javascript">
$(function () {
var data = [ ]]>{e1Array}<![CDATA[ ];
$.plot($("#placeholder1"), [ data ], {
series: {
bars: {
show: true,
barWidth: 1,
align: "center"
}
},
grid: {
hoverable: true,
clickable: true
},
xaxis: {
mode: "categories",
tickLength: 0
},
yaxis: {
min: 0,
max: 1,
ticks: 0
}
} );
});
var previousPoint = null;
$("#placeholder1").bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.datapoint) {
previousPoint = item.datapoint;
$("#tooltip1").remove();
showTooltip(item.pageX, item.screenY, item.series.data[item.dataIndex][0] + ': ' + item.series.data[item.dataIndex][1] + ' Einträge');
}
} else {
$("#tooltip1").remove();
previousPoint = null;
}
});
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: 100,
left: x,
border: '1px solid #fdd',
padding: '2px',
'background-color': '#fee',
opacity: 0.80
}).appendTo("#e1-container").fadeIn(0);
}
</script>
]]>
<div class="e1-container" id="e1-container">
<div id="placeholder1" class="e1"></div>
</div>
<![CDATA[
<script type="text/javascript">
This seems to be your problem, or at least the reason why FireBug does show html entities in your code. If you want to use cdata at all, you should place it inside of the <script> tags.
On why the tooltip is not shown at all, I can only guess, but for text content I'd recommend to use
$('<div id="tooltip"></div>').text(contents)
instead of using it as a html string.
You use appendTo(), which is fine.
You append the node only when the plothover flot event is fired.
This is correct, too.
So your code looks fine, you should probably look into this:
Jquery Flot "plothover" event not working
EDIT: You also can put the JS <script> after the HTML.
Do not directly add the contents inside the selector.
1) Create your DOM : var k = $('<div id="tooltip"></div>');
2) Fill your DOM :
// Add after
k.append(contents);
// Replace
k.html(contents);
// Replace and the content is just some text
k.text(contents);
3) Set the CSS : k.css({ ... })
4) Add the DOM to your page k.appendTo('#container');. You can also use $('#container').html(k); to replace the container contents and avoid to have a duplicate
In short :
var k = $('<div id="tooltip"></div>')
.append(contents)
.css({})
.appendTo('#container');
NOTE: The best way is to already create your tooltip div and just fill the elements to avoid to create two div with same ID, ... If you are afraid it perturbs the page, add display : none; to the CSS before to edit it, then change the classes when you edit it.
You will need to create div on 2 conditions :
The pages is created on load with variable number of components
You want to dynamically load CSS or JS.
I'm using threesixty plugin (jQuery) to display an 360 degrees view of an car.
<div class="threesixty" data-path="img/volvo/test/car{index}.jpg" data-count="6"></div>
</div>
<script type="text/javascript">
var $threeSixty = $('.threesixty');
$threeSixty.threeSixty({
dragDirection: 'horizontal',
useKeys: false,
draggable: true
});
</script>
I want to use select boxes to change the car shown, so users can pick their own car they want to see.
I tried to use the .change function to call a .data function to change the path.
<script type="text/javascript">
var $threeSixty = $('.threesixty');
$threeSixty.threeSixty({
dragDirection: 'horizontal',
useKeys: false,
draggable: true
});
$( "select" ).change(function() {
$('.threesixty').data('path', 'img/bmw/test/car{index}.jpg');
});
</script>
It does not seem to change anything.
When I use:
$( "select" ).change(function() {
$('.threesixty').attr('data-path', 'img/bmw/test/car{index}.jpg');
});
It does change the path but still does not show the new set of images.
Any help please?
I am trying to create a button with text inside using the Raphael JavaScript library. I would like to have a glow around the button on mouseover. I achieved this by using the set on rectangle and text and applying the glow on the set. I tried two approaches binding the mouseover and mouseout methods to the resulting button set. In the first case the glow stays if the cursor reaches the text, in the second one the glow disappears. Here is the code :
// canvas
var paper = Raphael(0, 0, "100%", "100%");
// background of the first button
var bBox1 = paper.rect(100, 100, 120, 50, 10).attr({
fill: 'darkorange',
stroke: '#3b4449',
'stroke-width': 2
});
// text of the first button
var text1 = paper.text(bBox1.attrs.x + bBox1.attrs.width / 2, bBox1.attrs.y + bBox1.attrs.height / 2, 'Click to expand').attr({
"font-family": "Helvetica",
"font-size": 16
});
// set of rectangle + text = button
var button1 = paper.set().attr({
cursor: 'pointer'
});
button1.push(bBox1);
button1.push(text1);
button1.mouseover(function (event) {
this.oGlow = bBox1.glow({
opacity: 0.85,
color: 'gray',
width: 15
});
}).mouseout(function (event) {
this.oGlow.remove();
});
// ********** now the second button **********
// background of the second button
var bBox2 = paper.rect(100, 200, 120, 50, 10).attr({
fill: 'lightblue',
stroke: '#3b4449',
'stroke-width': 2
});
// text of the first button
var text2 = paper.text(bBox2.attrs.x + bBox2.attrs.width / 2, bBox2.attrs.y + bBox2.attrs.height / 2, 'Click to expand').attr({
"font-family": "Helvetica",
"font-size": 16
});
// set of rectangle + text = button
var button2 = paper.set().attr({
cursor: 'pointer'
});
button2.push(bBox2);
button2.push(text2);
// function for the mousover event for buttons
var buttonMouseoverHandler = function (event) {
this.oGlow = this.glow({
opacity: 0.85,
color: 'gray',
width: 15
});
}
// function for the mouseout event
var buttonMouseoutHandler = function (event) {
this.oGlow.remove();
}
button2.mouseover(buttonMouseoverHandler);
button2.mouseout(buttonMouseoutHandler);
Here is a working jsfiddle example : http://jsfiddle.net/fkNhT/
I absolutely do not understand the difference in the behavior, can anyone please give me a hint?
Simple: In the first mouseover, you're setting the glow on the rect object, regardless of what's being moused over:
this.oGlow = bBox1.glow({...
In the second, you're setting it to "this", which would apply to the text object when you mouse over it:
this.oGlow = this.glow({...
How to prevent the loss of hover on interior elements of an element is one of the most common Raphael-related questions on SO. See this for a simple solution for small projects, and this open thread for an alternative for bigger projects.