Posts Tagged javascript
Image color picker in javascript that work without canvas in every browser
Posted by jcubic in Programming on January 8, 2013
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.
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>
How To Add Translation Feature To Twitter
Posted by jcubic in Programming on August 19, 2012
I don’t know about you but, I follow few peple that sometimes tweet in different language then English. And English is the only foreign language I know. So if I want to see what they tweet about sometimes I use google translate to read the content.
I always thought that it will be nice feature for Twitter to have translate button, so I created one, using WebSockets and Ruby.
So how I did this, first I downloaded websockets ruby library from github web-socket-ruby, I already had translation script written in Ruby that use google translate, so I added websocket server to it.
#!/usr/bin/ruby
require 'net/http'
require 'uri'
require 'optparse'
require 'json'
require 'socket'
require 'web_socket'
class NotConnectedException < Exception
end
def server(port, domains)
server = WebSocketServer.new(
:accepted_domains => domains,
:port => port)
puts("Server is running at port %d" % server.port)
server.run() do |ws|
puts("Connection accepted")
puts("Path: #{ws.path}, Origin: #{ws.origin}")
if ws.path == "/translate"
ws.handshake()
while data = ws.receive()
printf("Received: %p\n", data)
data = JSON.parse(data)
response = translate(data['text'], nil, data['to_lang']).join("\n")
ws.send(response)
printf("Sent: %p\n", response)
end
else
ws.handshake("404 Not Found")
end
puts("Connection closed")
end
end
def escape(o)
o.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
'%' + $1.unpack('H2' * $1.size).join('%').upcase
}.tr(' ', '+')
end
def translate(text, from=nil, to=nil, cookie=nil)
url = URI.parse("http://translate.google.com/translate_a/t")
query = "?hl=en&client=t&text=#{escape(text)}&multires=1&otf=1&pc=0&sc=1&ie=UTF-8&oe=UTF-8"
query += "&sl=" + (from ? from : 'auto')
if to
query += "&tl=#{to}"
end
begin
http = Net::HTTP.new(url.host)
res = http.get(url.path + query)
res.response['content-type'] =~ /charset=(.*)/
charset = $1
JSON.parse(res.body.gsub(/,{2,}/, ',').gsub(/,\]/, ']'))[0].map {|i|
# google sometimes put spaces around numbers
i[0].gsub(/\{ *([0-9]) *\}/, '{\1}')
}
rescue NoMethodError
raise NotConnectedException
rescue SocketError
raise NotConnectedException
rescue
end
end
def msg(str, type='info')
system("zenity --#{type} --title='translation' --text='#{str}'")
end
params = ARGV.getopts('i:o:gcsp:')
def error(msg, gui=false)
if gui
msg(msg, 'error')
else
puts msg
end
end
def usage()
puts "usage:"
puts "translate [-i <INPUT LANG>] -o <OUTPUT LANG> [MORE OPTIONS]"
puts "-g - show zenity dialog"
puts "-c - get input from clipboard"
puts "-s - run as server"
puts "-p - server port"
end
begin
if params['s']
begin
server(params['p'] ? params['p'].to_i() : 8080, 'twitter.com')
rescue Interrupt
puts "Server Exit"
end
else
if params['c']
input = `xclip -o -sel clip`
else
input = ARGF.read()
end
translation = translate(input, params['i'], params['o'])
if params['g']
msg(translation.join(". "))
else
translation.each{|sentence|
if sentence != ''
puts sentence
end
}
end
end
rescue JSON::ParserError => e
error("Response Error: " + e.message, params['g'])
rescue NotConnectedException
error("sorry but it seems that your internet connection is down", params['g'])
end
Then I created this bookmarklet. (I notice that profile page use jQuery.noConflict() so I can’t access it from bookmarklet. So here is updated code that insert jQuery script again – in use continuation to block execution of the script until jQuery is loaded). To use bookmarklet just copy code below and insert into url address bar when twitter tab is active
javascript:(function(continuation) {
function attr(elem, key, value) {
elem.setAttribute(document.createAttribute(key, value));
}
var script = (function() {
var head = document.getElementsByTagName('head')[0];
return function(src) {
var script = document.createElement('script');
script.setAttribute('src', src);
script.setAttribute('type', 'text/javascript');
script.setAttribute('async', 'false');
head.appendChild(script);
return script;
};
})();
script('https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js');
var interval = 100;
setTimeout(function() {
if (jQuery) {
continuation(jQuery.noConflict());
} else {
setTimeout(arguments.callee, interval);
}
}, interval);
})(function($) {
function translator(fun, lang) {
var socket = new WebSocket("ws://localhost:8080/translate");
socket.onopen = function() {
console.log("Socket has been opened!");
};
socket.onclose = function() {
console.log("closed");
};
return fun(function(text, respond) {
socket.onmessage = function(msg) {
respond(msg.data);
};
var data = JSON.stringify({to_lang: lang, text: text});
socket.send(data);
});
}
var translate_tweet = translator(function(translate) {
return function(content) {
var tweet_container = content.find('.js-tweet-text');
var tweet = tweet_container.html();
content.data('original', tweet);
var links = [];
var i = 0;
tweet = tweet.replace(/<a[^>]+>[^<]+<\/a>|<a[^>]+><s>(#|@)<\/s><b>[^<]+<\/b><\/a>/g, function(link) {
links.push(link);
return '{' + i++ + '}';
});
translate(tweet, function(result) {
for (var i=links.length; i--;) {
result = result.replace('{' + i + '}', links[i]);
}
tweet_container.html(result);
var actions = content.find('.tweet-actions');
if (actions.find('.action-orig-container').length == 0) {
actions.append('<li class="action-orig-container"><a href="#">Original</a></li>');
}
});
};
}, prompt('Select Language: af - afrikaans, sk - albánskej, ar - عربي, be - Беларускі, bg - Български, zh - 荃湾, zh - 太阳, hr - Hrvatski, cs - Český, da - Danske, et - Eesti, tl - filipiński, fi - Suomi, fr - Français, gl - galijski, el - Ελληνικά, iw - עברית, hi - हिन्दी, es - Español, nl - Nederlands, id - indonezyjski, ga - Gaeilge, is - Íslenska, ja - 日本語, yi - ייִדיש, ca - Català, ko - 한국의, lt - Lietuvos, lv - Latvijas, mk - Македонски, ms - Melayu, mt - Malti, de - Deutsch, no - Norsk, fa - فارسی, pl - polski, ru - Русский, ro - Română, sr - Српски, sk - Slovenský, sl - Slovenski, sw - Swahili, sv - Svenska, th - ภาษาไทย, tr - Türk, uk - Український, cy - walijski, hu - Magyar, vi - Việt, it - Italiano'));
$('.content').unbind('mouseover').live('mouseover', function() {
var $this = $(this);
if ($this.find('.action-trans-container').length == 0) {
$this.find('.action-fav-container').
after('<li class="action-trans-container"><a href="#">Translate</a></li>');
}
});
$('.action-orig-container').unbind('onclick').live('click', function() {
var content = $(this).parents('.content');
content.find('.js-tweet-text').html(content.data('original'));
content.find('.action-orig-container').remove();
return false;
});
$('.action-trans-container').unbind('onclick').live('click', function() {
translate_tweet($(this).parents('.content'));
return false;
});
});
CODE LICENSE: you can use the code for whatever purpose you like it’s realeas on Sharing Agreement.
Really wicked web application source code hiding
Posted by jcubic in Programming on March 11, 2011
I saw this video on YouTube from DefCon Conference.
I go to samy website, and it’s web application which look like Microsoft Windows. So first think I do to see how it is build. I look at source code and it’s look like there is no code at all, but in the middle (line 281) there is this
<script>/* No source for you! *// </script>
Before and after script tags are only empty lines (\n), I check the end of the line 283 and there is following code (line breaks and indentations are mine):
/.source.replace(/.{7}/g,function(w){document.write(
String.fromCharCode(parseInt(w.replace(/ /g,'0').
replace(/ /g,'1'),2)))});
And thats it. So where is the real code? And the answer is this:
- He encode all characters in html as binary and replace zeros as space and ones as tabulations. there is no string, but in 283 line there is this:
"*//"which is the end of multi-line comment and beginning of Regular Expression (which look like simple closing comment) - He get value of the string representation of the RegEx using source field
- replace all whitespace with
'0'and'1' - convert it to decimal
- get the value of characters encoded and print all of that out
Pretty clever.
Of course you can get generated code from a menu “View Generated Source” from WebDeveloper toolbar in Firefox or see the the DOM in Firebug.
jQuery splitter – split container
Posted by jcubic in Programming on March 6, 2011
JQuery Terminal Emulator Plugin
Posted by jcubic in Programming on December 16, 2010
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"].
Create nice looking blockquote with jquery and css
Posted by jcubic in Programming on October 19, 2010
If you want to create nice looking blockquotes on your web page here is simple plugin.

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">”</span>');
$(this).prepend('<span class="open">“</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
How to use and extend BiwaScheme
Posted by jcubic in Programming on May 17, 2010
BiwaScheme is scheme implementation in Javascript.
Here you can find scheme interpeter using BiwaScheme (using JQuery Terminal Emulator inside JQuery UI Dialog). If you want to download BiwaScheme package click here.
BiwaScheme use prototype javascript library.
If you wat to use interpreter in your own code you must:
- add this to head tag
<script type="text/javascript" src="src/development_loader.js"> </script>
or if you want to make distribution you must have make and YUI Compressor which require java
Uncomress package and type make in biwascheme directory it will create lib/biwascheme.js file which is compressed library. You must put it in head of your html file:
<script type="text/javascript" src="lib/biwascheme.js"> </script>
- Create instance of Interpreter class
var intepreter = new BiwaScheme.Interpreter();
- You can also put function for error handling to the constructor
var biwascheme = new BiwaScheme.Interpreter(function(e, state) { $('output').innerHTML += e.message; }); - If you want to result be proper displayed you must overwrite puts function
var output = $('ouptut'); function puts(str, no_newline) { if (no_newline) { output.innerHTML += str; } else { output.innerHTML += str + "<br />"; } } - Evaluating funtion should look like this:
var input = $('input'); var output = $('output'); function scheme_eval(e) { try { // show trace messages if (trace) { var opc = interpreter.compile(input.innerHTML); var dump_opc = (new BiwaScheme.Dumper()).dump_opc(opc); output .innerHTML += dump_opc; } interpreter.evaluate(shell.code_to_evaluate, function(result) { if (result != undefined) { result = BiwaScheme.to_write(result); output.innerHTML += '> ' + result; } }); } catch(e) { //this will never be evaluated because all errors are //pased to function pased to Interpreter constructor output.innerHTML += e.message; throw(e); } } - You could bind this function with onclick event
$('eval_btn').onclick = scheme_eval; - If you want to define new function which will be accessable in your scheme interpreter you should use define_libfunc function from global object BiwaScheme. First parametr is scheme name of the function, second and third are minimum and maximum of parameters and fourth is the anonimus function with one argument which is array of parameters pased to scheme procedure.
BiwaScheme.define_libfunc('env', 0, 0, function(args) { var result = new Array(); for(fun in window.BiwaScheme.CoreEnv) { result[result.length] = fun; } // result should be converted from array to scheme list return result.to_list(); });This function will return list of all function and variables in scheme global Environment.
The following scheme function will display that list:
(define (show-env) (let iter ((list (env))) (if (not (null? list)) (begin (display (car list)) (newline) (iter (cdr list))))))or simplier.
(define (show-env) (display (string-join (env) "\n")) (newline))
- If you want to define some variable you must put it in BiwaScheme.CoreEnv array.
If you want to define (in javascript) function with scheme code use BiwaScheme.define_scmfunc. First parameter is scheme name, second and third are minimum and maximum of parameters (BiwaScheme check this before function are evaluated) and the fourth one is string containing your scheme code (should be lambda expresion).
BiwaScheme.define_scmfunc('**', 1, 1, "(lambda (x y) \ (cond \ ((= y 0) 1) \ ((< y 0) (** (/ 1. x) (- y))) \ (else \ (let iter ((i 1) (result x)) \ (if (= i y) \ result \ (iter (+ i 1) (* result x)))))))");Former function define power with tail recursion.
You could also create scheme macro in javascript with BiwaScheme.define_syntax function. This function must return BiwaScheme.Pair object which will be evaluated. It accept single parameter which is scheme expression (tree build from
BiwaScheme.Pairobjects). This is example of using macros from javascript://this is helper Array method which traverse a tree build with arrays //and create tree of Symbols // it use to_list function wich is defined by BiwaScheme Array.prototype.to_tree = function() { for(var i in this) { if (this[i] instanceof Array) { return this[i].to_tree(); } } return this.to_list(); }; BiwaScheme.define_syntax('foo', function(expr) { return [BiwaScheme.Sym("display"), [BiwaScheme.Sym("quote"), expr.cdr.to_array().to_tree()] ].to_tree(); });This code create new macro foo which simply display expression passed as parameters. Note that the whole expression is in expr.cdr filed.
- In interpeter you could also define macros (like common lisp macros) with define-macro expresion.
(define-macro (for params . body) `(let iter ((,(car params) ,(cadr params))) (if (< ,(car params) ,(caddr params)) (begin ,@body (iter (+ ,(car params) ,(if (= (length params) 4) (cadddr params) 1)))))))The former code define for loop (which use tail recursion), you could use it with
(for (variable init end step) code):(for (i 1 10) (display i) (newline))
or
(for (i 10 100 10) (display i) (newline))
Which display numers: 10 20 30 40 50 60 70 80 90 100.
Update: Check also Extending Scheme interpreter in BiwaScheme wiki on GitHub.

