Posts Tagged jquery

Working with SVG in jQuery

I recently notice that if you create element like a circle in SVG (inline SVG embedded into HTML), using inspector/firebug or jQuery, your circle is not visible on SVG until you refresh the SVG, I found a hack to force refresh of the SVG, I just get text of the SVG and insert it again into the DOM, and all elements that were not visible like circle mention before will be rendered.

Here is referesh function, as jQuery plugin


$.fn.xml = function() {
    return (new XMLSerializer()).serializeToString(this[0]);
};

$.fn.DOMRefresh = function() {
    return $($(this.xml()).replaceAll(this));
};

Those plugins should work with every XML embeded into HTML not only SVG. Don’t look very nice but it work, but I found a better way fix jQuery to work with SVG. I found that when I use function document.createElementNS instead of document.createElement elements added to inline SVG using for instance appendChild function everything work fine. So only thing that need to be done for jQuery to work with inline SVG is to replace this function if element is SVG. First I wrote method in jQuery object that test if element is SVG element, there are only three elements that have the same name in HTML and SVG is a, script, style and title tags so I didn’t put them in.

isSVGElement: function( o ) {
        if (o instanceof SVGElement) {
            return true;
        } else {
            if (typeof o === 'string') {
                return $.inArray(o, ['altGlyph', 'altGlyphDef',
                                     'altGlyphItem', 'animate',
                                     'animateColor', 'animateMotion',
                                     'animateTransform', 'circle',
                                     'clipPath', 'color-profile',
                                     'cursor', 'defs', 'desc', 'ellipse',
                                     'feBlend', 'feColorMatrix',
                                     'feComponentTransfer',
                                     'feComposite', 'feConvolveMatrix',
                                     'feDiffuseLighting',
                                     'feDisplacementMap',
                                     'feDistantLight', 'feFlood',
                                     'feFuncA', 'feFuncB', 'feFuncG',
                                     'feFuncR', 'feGaussianBlur',
                                     'feImage', 'feMerge', 'feMergeNode',
                                     'feMorphology', 'feOffset',
                                     'fePointLight',
                                     'feSpecularLighting', 'feSpotLight',
                                     'feTile', 'feTurbulence', 'filter',
                                     'font', 'font-face',
                                     'font-face-format',
                                     'font-face-name', 'font-face-src',
                                     'font-face-uri', 'foreignObject',
                                     'g', 'glyph', 'glyphRef', 'hkern',
                                     'image', 'line', 'linearGradient',
                                     'marker', 'mask', 'metadata',
                                     'missing-glyph', 'mpath', 'path',
                                     'pattern', 'polygon', 'polyline',
                                     'radialGradient', 'rect',
                                     'set', 'stop', 'svg',
                                     'switch', 'symbol', 'text',
                                     'textPath', 'tref',
                                     'tspan', 'use', 'view',
                                     'vkern']) !== -1;
            }
        }
    }

I get the list of elements from Mozilla MDN.

I added this method to main jQuery.extend({ that add methods to jQuery object. Next thing is to replace createElement with createElementNS, there are only 2 places with this in parseHTML (in the same jQuery.extend) and createSafeFragment function, only one is responsible for inserting elements – parseHTML. Below is the code for that function.


	parseHTML: function( data, context, keepScripts ) {
		if ( !data || typeof data !== "string" ) {
			return null;
		}
		if ( typeof context === "boolean" ) {
			keepScripts = context;
			context = false;
		}
		context = context || document;

		var parsed = rsingleTag.exec( data ),
			scripts = !keepScripts && [];

		// Single tag
		if ( parsed ) {
			if ( jQuery.isSVGElement( parsed[1] ) ) {
				return [ context.createElementNS(
					"http://www.w3.org/2000/svg",
					parsed[1]) ];
			} else {
				return [ context.createElement( parsed[1] ) ];
			}
		}

		parsed = jQuery.buildFragment( [ data ], context, scripts );
		if ( scripts ) {
			jQuery( scripts ).remove();
		}
		return jQuery.merge( [], parsed.childNodes );
	},

Unfortunetnly not all manupulation methods that create new elements will work but it’s better then refresh hack. The stuff that don’t work is when you create more then one element from a string or if you put some attributes. In this case jQuery use document fragments and innerHTML to create the DOM. If we will want to fix that too we will need to write a parser that will call createElementNS.

You can also include those function after you load jQuery so original code will not be changed.

The other way is to use document.createElementNS and element.setAttributeNS that need to be used if you want to add xlink:href attribute (it use http://www.w3.org/1999/xlink namespace).

,

Leave a comment

Image color picker in javascript that work without canvas in every browser

If you want to create color picker from image in javascript you probably will use canvas, but what if you need it work in IE as I needed. You can use some server side help to fetch pixels data from the server. I use php for that and GD library. The code is below.

cross-browser color picker

Server side code that return json pixel data


<?php

function rgb($color) {
    $result[] = ($color >> 16) & 0xFF;
    $result[] = ($color >> 8) & 0xFF;
    $result[] = $color & 0xFF;
    return $result;
}

function imagecreatefrom($filename) {
    $path = pathinfo($filename);
    switch($path['extension']) {
        case 'png':
            return imagecreatefrompng($filename);
        case 'jpg':
            return imagecreatefromjpeg($filename);
        case 'gif':
            return imagecreatefromgif($filename);
        default:
            return null;
    }
}

function getImageData($filename) {
    list($width, $height) = getimagesize($filename);
    $image = imagecreatefrom($filename);
    $image_data = array();
    for ($y = 0; $y < $height; ++$y) {
        $row = array();
        for ($x = 0; $x < $width; ++$x) {
            $row[] = rgb(imagecolorat($image, $x, $y));
        }
        $image_data[] = $row;
    }
    return $image_data;
}

if (isset($_GET['filename'])) {
    $filename = $_GET['filename'];
    if (file_exists($filename)) {
        $result = array(
            'error' => null,
            'result' => getImageData($filename)
        );
    } else {
        $result = array(
            'error' => "The file '$filename' don't exist",
            'result' => null
        );
    }
} else {
    $result = array(
        'error' => "You need to put filename",
        'result' => null
    );
}
header('Content-Type: application/json');
echo json_encode($result);

?>

Then you can fetch the data using ajax and add get invidial pixels on mousemove


    var img = $('img');
    $.getJSON('image_data.php', {filename: img.attr('src')}, function(data) {
        if (data.error) {
            alert(data.error);
        } else {
            $('.eyedropper').click(function() {
                picker = true;
                return false;
            });
            img.mousemove(function(e) {
                if (picker) {
                    var x = Math.round(e.pageX - offset.left);
                    var y = Math.round(e.pageY - offset.top);
                    if (x >= 0) {
                        $('.color').css('background-color',
                                        'rgb('+data.result[y][x].join(',')+')');
                    }
                }
            }).click(function(e) {
                picker = false;
            });
        }
    });

Now all you need to have is element with class eyedropper like a link in your html:


<a href="#" class="eyedropper">pick the color</a>

, ,

3 Comments

jQuery splitter – split container

This is my latest jquery plugin — “splitter” which splits content vertically or horizontally with movable element between them, that allow to change the proportion of two element. You can get it from github. The demo is here.

, ,

21 Comments

JQuery Terminal Emulator Plugin

My new project JQuery Terminal Emulator. It’s a plug-in which can be used to add Command Line interface to your application. You can use it to easily create server configuration tool or can be help in debugging or testing server side of AJAX applications. You can put lots of options in one place.

You can create command line interface to JSON-RPC in one line of code. Just set the path to rpc service.

$(document.documentElement).terminal("json-rpc-service.php");

If you want to use authentication.

$(document.documentElement).terminal("json-rpc-service.php", {
    login:true
});

And when user type user and password it will call login rpc method, get the token and pass that token to all methods on the server when user type command. So when user type for example add-user foo foo@bar.com it will call json-rpc add-user with parameters [token, "foo", "foo@bar.com"].

, , ,

1 Comment

Create nice looking blockquote with jquery and css

If you want to create nice looking blockquotes on your web page here is simple plugin.

nice looking blockquote

First basic css

.quote {
    font-size: 2em;
    font-family: Times New Roman, times, serif;
    position: relative;
}
.quote p {
    margin: auto;
    text-align: justify;
}
.quote span {
    font-size: 4em;
}
.quote span.open {
    position:absolute;
    top:-0.35em;
    left:0;
}
.quote span.close {
    position:absolute;
    bottom: -0.8em;
    right: 0;
}

code for the plugin

$.fn.quote = function(params) {
    $(this).addClass('quote');
    var width = params && params.width ? params.width : 400;
    $(this).css('width', width);
    $(this).html('<p>' + $(this).html() + '</p>');
    $(this).find('p').css('width', width - 120);
    $(this).append('<span class="close">&rdquo;</span>');
    $(this).prepend('<span class="open">&ldquo;</span>');
};

create basic html

<blockquote>Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Nulla sed dolor nisl, in suscipit justo. 
Donec a enim et est porttitor semper at vitae augue.
</blockquote>

And run the plugin

$(document).ready(function() {

    $('blockquote').quote({'width': 500});

});

The default width is 400 px

lt

, ,

Leave a comment

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: