color to B/W javascript affect - javascript

Is there any known/simple/open-source library that provide
a javascript function that will switch colored picture that is displayed in an html page into a black and white
That can be used in all the most used browsers (IE, FireFox, Chrome)?
I mean something like:
<html>
...
<img id="myPic" src="pic.jpg">
...
<script type="text/javascript">
function onEvent(){
var pic = document.getElementById("myPic");
magicFunctionToBlackAndWhite(pic);
}
</script>
</html>
looking for that magicFunctionToBlackAndWhite()

There's no one solution that works across all browsers, but you can combine different solutions:
For IE, use the following CSS: filter: Gray
A lot of other browsers supports canvas, so you should be able to use this javascript code for that.
Of course it should't be too much of a hassle to make an image b/w in a serverside language such as .net, so you could always have a javascript that in principle does something like the following:
var imgs = document.getElementsByTagName('img');
for(var i = 0; i < imgs.length; i++) {
imgs[i].src = 'convertimage.aspx?img=' + imgs[i].src;
}
...and then have all of the magic happening on the server.

That might be somehow possible by using the <canvas> element, but I would recommend you to do the black and white versions yourself, either manually or through some sort of script. Trust me – it'll save you a lot of trouble.

Related

Mobile first when using match media?

I have a page that uses multiple form elements. Far too many for a smartphone without scrolling, which I don't want. To solve this problem, I put the form elements in a carousel.
When I don't need the carousel (larger displays) I need to eliminate it. The only way I know of to do this is to reassign the parent properties of the carousel items and then remove the carousel.
This approach works fine using java-script. However, to pull this off I would need to use match media to call the java-script functions. Since most legacy browsers (which don't support match media) are used by desktops wouldn't this go against mobile first development?
Would it be wiser to design for legacy browsers and then upgrade the page for newer, more robust devices that can understand more updated languages or am I approaching this problem entirely wrong? I would rather not add a polyfill to fix this problem if I don't have to. Forgive my ignorance if I'm not seeing the simple solution here.
Here is a snippet that changes the parent div for large displays at codepen.
// Transfer elements from carousel to a larger div display
function SetParentDiv() {
var newParent = document.getElementById('LargeDisplayPage');
var oldParent = document.getElementById('1');
// Carousel items are 3 divs with numbered id's
for (var x=1; x < 4; x++) {
oldParent = document.getElementById(x);
while (oldParent.childNodes.length > 0) {
newParent.appendChild(oldParent.childNodes[0]);
}; ///endwhile
}; // endfor
document.getElementById('SmallDevicePage').style.display = 'none';
...
Here is the full Code Pen

Image for <option> not working in IE

My requirement is to add images inside <option>. I have used the below code to display images in FF.
[Script]
var items = $("#ShipCountry option").children(); //dropdown options
for (i = 0; i < items.length; i++) {
$(items[i]).html("<img src='/Images/" + $(items[i]).html() + ".gif'></img>"); // adding image
}
This code works in FF but not in other browsers. I do not want to implement this logic using CSS as i need to display large number of images (options).
Is that possible without CSS for all browsers?
There is no way to make this work cross-browser, as lots of browsers restrict what you can do with the <option> tag. I'm surprised it works in Firefox to be honest. You might want to look into Select2 which makes this possible cross browser, and has great documentation.

Measuring the string width in Javascript

I'm trying to precisely fit a string into a certain width. This means the font-size changes depending on the string. I now use the following function, using jQuery:
function fontResize ( )
{
for (var i = $("#date").css("font-size").slice(0, -2); $("#date").width() < $("#clock").width(); i++)
$("#date").css("font-size", i.toString() + "px");
}
The idea is that I set the font-size in the CSS to the lowest possible value. I initialize the loop with this value and increment the font-size with 1 until the string is wider than the width of the containing element. The string in this case is "date" and the containing element is "clock".
Although this works, I think the main disadvantage is that the string has to be first drawn before the width can be determined. This means I cannot call this function before loading the body.
If anyone knows a better way to do this please let me know! Thanks.
To make sure you're getting all the styles and such applied to it that will be applied when the page is fully rendered, yes, you do want to put the element in the DOM (and in the right place in the DOM) before you do your measurement stuff. But you don't have to wait until everything else is there (unless you think it will affect the styling of the string you're measuring). You can put your code in a script block immediately after the element in question — no waiting for ready. The date element will be there and accessible, according to Google's Closure library engineers. E.g., if date is a span:
<body>
...
<span id="date">December 13th</span>
<script>fontResize();</script>
...
...
</body>
It's unfortunate to intermix code and markup like that (particularly if you have separate teams doing the markup and the code), but if your requirement is to size the text absolutely as soon as possible, that's how.
The above also assumes your fontResize function is already loaded (e.g., in a script block higher on the page). This is another reason it's unfortunate to mix markup and code like this, because normally of course you want to put your scripts at the bottom, just before closing the body tag.
However: It may be worth experimenting to see if you can do your resizing in the script you put just before the closing body tag instead. There'd be a small window of opportunity for the page not to look right, but quite small and of course pages tend to look a little funny as they load anyway. Then you wouldn't have the intermixing problem and wouldn't have to load your scripts early. You may find that the just-before-the-closing-body-tag is soon enough.
How about using the canvas, and the measureText method?
$(function () {
var canvas = $("canvas")[0];
var context = canvas.getContext("2d");
var text = "hello world";
context.font = "40pt Calibri";
var metrics = context.measureText(text);
alert(metrics.width);
});

WebP Image Replacement

My end goal is to detect if the browser is capable of displaying webp images. If it is, replace all the images on the page with their webp equivalent (located in the same directory with the same name, just different extension)
Currently I have a script that successfully detects if the browser is able to display webp
(function(){
var WebP=new Image();
WebP.onload=WebP.onerror=function(){
if(WebP.height!=2){
console.log("You do not have WebP support.");
} else {
console.log("You do have WebP support.");
}
};
WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
})();
Inside the case for having webp support I have tried the following code but been unsuccessful.
// replace .gif with .webp
var allImages = document.body.getElementsByTagName("img");
var length = allImages.length;
var i;
for(i = 0; i < length; i++){
allImages[i].src.replace("png", "testtest");
console.log(allImages[i]);
}
When placed in the header the console does correctly show all of the image tags, but the source has not been changed from the filename.png that it originally was.
Any ideas on what is being done incorrectly?
Edit: I found found out the problem with why it was not loading the images, thanks to wsanville. Looking at the network tab in chrome however still reveals that I am loading both the png and now the webp image as well. How can I prevent the png image from loading in the first place?
The replace function returns a string, it doesn't mutate it. You just need to assign the value back:
allImages[i].src = allImages[i].src.replace("old", "new")
Edited for comment:
All browsers will download the corresponding file in the src attribute of an image. As an alternate to your approach, I suggest storing the file name in a different attribute of the img tag.
Your image tags could look like:
<img alt="" data-png-source="/path/to/image.png" />
The corresponding Javascript could set the src attribute to the correct version.
var supportsWebP = true; //set this variable properly
for(i = 0; i < length; i++)
{
var image = allImages[i];
var pngSource = image.getAttribute('data-png-source');
image.src = supportsWebP ? pngSource.replace('.png', '.webp') : pngSource;
}
I know this a very old question, but as I looked for a way to replace webp images with corresponding jpgs, I didn't find much.
With this post, I put this together which seems to work through IE 9.
(It might actually work further back with an older jQuery version, but I'm using jQuery 2.1.1 which breaks in IE <= 8 so I'm not certain)
It checks for .webp support, then if the browser doesn't support .webp, it replaces all occurrences with a .jpg equivalent.
$(function() {
var WebP=new Image();
WebP.onload=WebP.onerror=function(){
if(WebP.height!=2){
$('img[src$=".webp"]').each(function(index,element) {
element.src = element.src.replace('.webp','.jpg');
});
}
};
WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
});
If you have (some) control of the server, you can use content negotiation instead of javascript. See http://httpd.apache.org/docs/2.2/content-negotiation.html for how it's done in Apache.
You are actually trying to solve a variation of the classic responsive image problem.
The problem you have with changing the image src attributes is that a modern browser will look ahead and start downloading images with the wrong extension. You probably don't want to download images you aren't going to use.
The trick is to place the image inside a noscript tag, then progressively enhance that by changing the path as you read the textContent of the tag. In older browsers you will need a simple polyfill to read out the content of noscript tags.
You can view my series on responsive images and webP support here. View an example here based on Ethan Marcotte's classic responsive design.

In firefox, how can I change an existing CSS rule

In firefox, I have the following fragment in my .css file
tree (negative){ font-size: 120%; color: green;}
Using javascript, how do I change the rule, to set the color to red?
NOTE:
I do not want to change the element.
I want to change the rule.
Please do not answer with something like
...
element.style.color = 'red';
What you're looking for is the document.styleSheets property, through which you can access your css rules and manipulate them. Most browsers have this property, however the interface is slightly different for IE.
For example, try pasting the following in FF for this page and pressing enter:
javascript:alert(document.styleSheets[0].cssRules[1].cssText)
For me that yields the string "body { line-height: 1; }". There are methods/properties that allow you to manipulate the rules.
Here's a library that abstracts this interface for you (cross-browser): http://code.google.com/p/sheetup/
function changeCSSRule (stylesheetID, selectorName, replacementRules) {
var i, theStylesheet = document.getElementById(stylesheetID).sheet,
thecss = (theStylesheet.cssRules) ? theStylesheet.cssRules : theStylesheet.rules;
for(i=0; i < thecss.length; i++){
if(thecss[i].selectorText == selectorName) {
thecss[i].style.cssText = replacementRules;
}
}
};
You can change CSS rules in style sheets through the CSS Object Model (currently known as DOM Level 2 Style). However, if you literally have "tree (negative)" in your style sheet that rule will be dropped and not appear in the Object Model at all.
As there is no HTML element tree I am going to assume that tree is the id or class of another element.
You would first retrieve the DOM element by id:
var tree = document.getElementById("tree");
Now tree represents your DOM element and you can manipulate it any way you like:
tree.style.color = "red";
Here is a great reference for mapping css properties to their javascript equivalent.
I'm not sure you can do actual class/selector overrides. You would need to target each element that used the .tree class and set the CSS. The quickest and easiest way would be through jQuery (or another similar framework):
$('.tree').each(function() { this.style.color = "red"; });
You could even use the built-in CSS functions:
$('.tree').css('color', 'red');
(I did it the first way to show you how standard JS would do it. The $(...) part is jQuery for selecting all elements with the .tree class. If you're not using jQuery, you'd need alternative code.)
If tree is an ID, not a class (there should only be one on the page) so using getElementById should be fine. Your code should look like the other answer.
for( var i in document.getElementsByTagName("tree") ){
document.getElementsByTagName("tree")[i].style.color = "red";
}
As I said in another answer's comment, I've never seen this done how you want. I've only ever targeted elements the same way as the CSS renderer would and changed each element style.
I did see this though: jQuery.Rule
It sounds like it does what you want but the demo causes my browser to flip out a bit. I'd invite you to look at the source to see it really does do what you want, and if you want to use it without jQ, use it as a starting point.
Edit: yes this should work. It works by appending another <style> tag to the page and writing out your overrides within. It's fairly simple to follow if you wanted to port it to plain JS.
For debugging, you can use Firebug to change the CSS rules on-the-fly.
If you want to change the rendered css rules from one page request to the next then some sort of server-side scripting will be required. Otherwise the original style sheet would simply reload at the next page request.
If you want to use an event on the first page to force the server-side action then you can use AJAX to actually change the CSS rule for the user.
"I want to change the rule so that
when I navigate to the next page, I
don't have to make all the changes
again."
It sounds like what you might want then is a remote request ("ajax") back to the server with the request you want to make, and generate a dynamic stylesheet which is sent back to the client?
How/why is this Firefox specific?
I want to change the rule so that when I navigate to the next page, I don't have to make all the changes again.
There are two approaches I can think of here. Namely client side and/or server side.
Client side:
Store the theme setting into cookies and load them up next time by javascript.
Server side:
If your site have an login system, you may also store the user preference into the database and generate the webpages with this inforamtion in mind next time on.
Utimately, you are still writing things like element.style.color =. But, they should get what you want.

Categories

Resources