Commits

Bogdan Savluk committed a770ed9

Separate repository for extension

Comments (0)

Files changed (17)

CoordinatePicker.php

+<?php
+
+/**
+ * Widget to use coordinate picker jQuery plugin.
+ *
+ * Link to original jQuery plugin:
+ * @link https://github.com/davidsalazar/coordinate-picker
+ *
+ * @author Bogdan Savluk <savluk.bogdan@gmail.com>
+ */
+class CoordinatePicker extends CWidget
+{
+    /** @var CModel model */
+    public $model;
+
+    /** @var string latitude attribute name in $model */
+    public $latitudeAttribute = 'latitude';
+
+    /** @var string longitude attribute name in $model */
+    public $longitudeAttribute = 'longitude';
+
+    /** @var string latitude input id */
+    public $latitudeInputId;
+
+    /** @var string longitude input id */
+    public $longitudeInputId;
+
+    /** @var string Label for picker link, when not set “Pick Coordinates” will be used */
+    public $label = null;
+    /** @var string An absolute URL to the published assets */
+    public $assets;
+
+    /**
+     *  Publish assets and generate input ids when they is not set
+     */
+    public function init()
+    {
+        $this->assets = Yii::app()->getAssetManager()->publish(dirname(__FILE__) . '/CoordinatePicker/coordinate_picker'); //, false, -1, true
+        if (!isset($this->latitudeInputId)) {
+            $this->latitudeInputId = CHtml::activeId($this->model, $this->latitudeAttribute);
+        }
+        if (!isset($this->longitudeInputId)) {
+            $this->longitudeInputId = CHtml::activeId($this->model, $this->longitudeAttribute);
+        }
+    }
+
+    /**
+     *  Register required scripts and styles, render widget
+     */
+    public function run()
+    {
+        $cs = Yii::app()->clientScript;
+        $cs->registerCoreScript('jquery');
+        $cs->registerScriptFile($this->assets . '/jquery.coordinate_picker.js');
+        $cs->registerCssFile($this->assets . '/styles/smodal/shadow.css');
+
+        if (!isset($this->label)) $this->label = 'Pick Coordinates';
+
+        echo CHtml::link($this->label, '#', array('id' => $this->getId()));
+
+        $cs->registerScript($this->getId() . 'script', <<<EOD
+$('#{$this->getId()}').coordinate_picker({
+	'lat_selector':  '#{$this->latitudeInputId}',
+	'long_selector': '#{$this->longitudeInputId}'
+});
+EOD
+        );
+
+    }
+
+}

CoordinatePicker/coordinate_picker/jquery.coordinate_picker.js

+jQuery(function ($) {
+
+    $.findJsPath = function (js) {
+
+        var relative_js = false;
+
+        // if js supplied, use that to find path relative to that file.
+        if (js) {
+            $('script').each(function () {
+                var $this = $(this);
+                var src = $this.attr('src');
+                if (src && src.substring(src.length - js.length) == js) {
+                    relative_js = src;
+                    return true;
+                }
+            });
+        }
+
+        // Fallback to using the first script tag
+        else if ($('script').length) {
+            relative_js = $('script').attr('src');
+        }
+
+        var js_path = '';
+        if (relative_js) {
+            var _js_path = relative_js.split('/')
+            _js_path && _js_path.pop();
+            if (_js_path && _js_path.length) {
+                js_path = _js_path.join('/');
+            }
+        }
+        return js_path ? js_path + '/' : '';
+
+    };
+
+    var js_path = $.findJsPath('jquery.coordinate_picker.js');
+
+    $.get(js_path + 'jquery.smodal.js');
+
+    $.coordinate_picker = {settings:{}};
+    $.fn.coordinate_picker = function (options) {
+
+        var settings = {
+            lat_selector:'#lat',
+            long_selector:'#long',
+            onComplete:false
+        };
+
+        if (options) {
+            $.extend(settings, options);
+        }
+
+        $.coordinate_picker.settings = settings;
+        return this.each(function () {
+
+            var $this = $(this);
+            $this.click(function (e) {
+                e.preventDefault();
+                $.smodal({
+                    src:js_path + 'map.html', width:700, height:500
+                }).open();
+
+            });
+
+        });
+
+    };
+
+
+});
+

CoordinatePicker/coordinate_picker/jquery.input_hint.js

+(function ($) {
+
+    if (!$.isFunction($.fn.selectRange)) {
+        $.fn.selectRange = function (start, end) {
+            var el = $(this).get(0);
+            if (!el) return;
+            else if (el.setSelectionRange) {
+                el.focus();
+                el.setSelectionRange(start, end);
+            } /* WebKit */
+            else if (el.createTextRange) {
+                var range = el.createTextRange();
+                range.collapse(true);
+                range.moveEnd('character', end);
+                range.moveStart('character', start);
+                range.select();
+            } /* IE */
+            else if (el.selectionStart) {
+                el.selectionStart = start;
+                el.selectionEnd = end;
+            }
+        };
+    }
+
+    $.fn.input_hint = function (settings) {
+        var config = {class_name:'label'};
+
+        if (settings) {
+            $.extend(config, settings);
+        }
+
+        var $selector = this;
+
+        var unload = function () {
+            $selector.each(function () {
+                var $this = $(this);
+                if ($this.attr('value') == $this.attr('title'))
+                    $this.attr('value', '');
+
+            });
+        };
+
+        $(window).unload(function () {
+            unload();
+        });
+
+        return $selector.each(function () {
+
+            var $this = $(this);
+
+            if ($this.attr('value').length == 0)
+                $this.attr('value', $this.attr('title')).addClass(config.class_name);
+
+            $this.focus(
+                function () {
+                    if ($this.attr('value') == $this.attr('title'))
+                        $this.selectRange(0, 0);
+                }).click(
+                function () {
+                    if ($this.attr('value') == $this.attr('title'))
+                        $this.selectRange(0, 0);
+                }).keypress(
+                function () {
+                    if ($this.attr('value') == $this.attr('title'))
+                        $this.attr('value', '').removeClass(config.class_name);
+                }).keyup(
+                function () {
+                    if ($this.attr('value') == $this.attr('title'))
+                        $this.addClass(config.class_name);
+                    else
+                        $this.removeClass(config.class_name);
+                }).blur(function () {
+                    if ($this.attr('value') == '')
+                        $this.attr('value', $this.attr('title')).addClass(config.class_name);
+                });
+
+            var $form = $this.parents('form');
+            if (!$form.data('input_hint_event')) {
+                $form.submit(function () {
+                    unload();
+                });
+                $form.data('input_hint_event', true);
+            }
+
+        });
+
+        return this;
+    };
+
+})(jQuery);

CoordinatePicker/coordinate_picker/jquery.smodal.js

+/// <reference path="$-1.3.2.min-vsdoc.js" />
+
+/************************************************************************************************************
+ * SIMPLE MODAL v 2.0
+ * © 2009 FISHBOWL MEDIA LLC
+ * http://fishbowlmedia.com
+ ***********************************************************************************************************/
+
+(function ($) {
+
+    /**********************************
+     * CUSTOMIZE THE DEFAULT SETTINGS
+     * Ex:
+     * var _settings = {
+     *     id: 'modal',
+     *     src: function(sender){
+     *        return $(sender).attr('href');
+     *    },
+     *     width: 800,
+     *     height: 600
+     * }
+     **********************************/
+    var _settings = {
+        width:800, // Use this value if not set in CSS or HTML
+        height:600, // Use this value if not set in CSS or HTML
+        overlayOpacity:.85, // Use this value if not set in CSS or HTML
+        id:'modal',
+        src:function (sender) {
+            return $(sender).attr('href');
+        },
+        fadeInSpeed:0,
+        fadeOutSpeed:0,
+        onLoad:false
+    }
+
+    /**********************************
+     * DO NOT CUSTOMIZE BELOW THIS LINE
+     **********************************/
+    var _modal = function (sender, params) {
+        this.options = {
+            parent:null,
+            overlayOpacity:null,
+            id:null,
+            content:null,
+            width:null,
+            height:null,
+            modalClassName:null,
+            imageClassName:null,
+            closeClassName:null,
+            overlayClassName:null,
+            src:null,
+            onLoad:false
+        }
+        this.options = $.extend({}, options, _defaults);
+        this.options = $.extend({}, options, _settings);
+        this.options = $.extend({}, options, params);
+        this.close = function () {
+            $('.' + options.modalClassName + ', .' + options.overlayClassName).fadeOut(_settings.fadeOutSpeed, function () {
+                $(this).unbind().remove();
+            });
+        }
+        this.open = function () {
+            if (typeof options.src == 'function') {
+                options.src = options.src(sender)
+            } else {
+                options.src = options.src || _defaults.src(sender);
+            }
+
+            var fileExt = /^.+\.((jpg)|(gif)|(jpeg)|(png)|(jpg))$/i;
+            var contentHTML = '';
+            if (fileExt.test(options.src)) {
+                contentHTML = '<div class="' + options.imageClassName + '"><img src="' + options.src + '"/></div>';
+
+            } else {
+                contentHTML = '<iframe id="coord_selector_iframe" name="coord_selector_iframe" width="' + options.width + '" height="' + options.height + '" frameborder="0" scrolling="no" allowtransparency="true" src="' + options.src + '">&lt/iframe>';
+            }
+            options.content = options.content || contentHTML;
+
+            if ($('.' + options.modalClassName).length && $('.' + options.overlayClassName).length) {
+                $('.' + options.modalClassName).html(options.content);
+            } else {
+                $overlay = $((_isIE6()) ? '<iframe id="coord_selector_iframe" name="coord_selector_iframe" src="BLOCKED SCRIPT\'&lt;html&gt;&lt;/html&gt;\';" scrolling="no" frameborder="0" class="' + options.overlayClassName + '"></iframe><div class="' + options.overlayClassName + '"></div>' : '<div class="' + options.overlayClassName + '"></div>');
+                $overlay.hide().appendTo(options.parent);
+
+                $modal = $('<div id="' + options.id + '" class="' + options.modalClassName + '" style="width:' + options.width + 'px; height:' + options.height + 'px; margin-top:-' + (options.height / 2) + 'px; margin-left:-' + (options.width / 2) + 'px;">' + options.content + '</div>');
+                $modal.hide().appendTo(options.parent);
+
+                $close = $('<a class="' + options.closeClassName + '"></a>');
+                $close.appendTo($modal);
+
+                var overlayOpacity = _getOpacity($overlay.not('iframe')) || options.overlayOpacity;
+                $overlay.fadeTo(0, 0).show().not('iframe').fadeTo(_settings.fadeInSpeed, overlayOpacity);
+                $modal.fadeIn(_settings.fadeInSpeed);
+
+                $close.click(function () {
+                    $.smodal().close();
+                });
+                $overlay.click(function () {
+                    $.smodal().close();
+                });
+            }
+
+            if ($.isFunction(options.onLoad)) {
+                $('#coord_selector_iframe').load(options.onLoad);
+            }
+
+        }
+        return this;
+    }
+    var _isIE6 = function () {
+        if (document.all && document.getElementById) {
+            if (document.compatMode && !window.XMLHttpRequest) {
+                return true;
+            }
+        }
+        return false;
+    }
+    var _getOpacity = function (sender) {
+        $sender = $(sender);
+        opacity = $sender.css('opacity');
+        filter = $sender.css('filter');
+
+        if (filter.indexOf("opacity=") >= 0) {
+            return parseFloat(filter.match(/opacity=([^)]*)/)[1]) / 100;
+        }
+        else if (opacity != '') {
+            return opacity;
+        }
+        return '';
+    }
+    var _defaults = {
+        parent:'body',
+        overlayOpacity:85,
+        id:'modal',
+        content:null,
+        width:800,
+        height:600,
+        modalClassName:'modal-window',
+        imageClassName:'modal-image',
+        closeClassName:'close-window',
+        overlayClassName:'modal-overlay',
+        src:function (sender) {
+            return $(sender).attr('href');
+        },
+        onload:false
+    }
+
+    $.smodal = function (options) {
+        return _modal(this, options);
+    }
+    $.smodal.open = function () {
+        _modal().open();
+    }
+    $.smodal.close = function () {
+        _modal().close();
+    }
+    $.fn.smodal = function (options) {
+        return _modal(this, options);
+    }
+
+
+})(jQuery);

CoordinatePicker/coordinate_picker/map.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <title>Google Map Coordinates Selector</title>
+    <link rel="stylesheet" href="styles/map.css" type="text/css" media="screen" title="no title" charset="utf-8"/>
+    <script type="text/javascript" charset="utf-8" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
+    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
+    <script src="jquery.input_hint.js" type="text/javascript" charset="utf-8"></script>
+    <script src="map.js" type="text/javascript" charset="utf-8"></script>
+    <link rel="stylesheet" href="styles/map.css" type="text/css" media="screen" charset="utf-8"/>
+
+</head>
+
+<body>
+
+<div id="wrapper">
+    <div id="map_canvas"></div>
+    <form id="search_map_form" class="clearfix">
+        <input type="text" name="search_map" value="" title="Search Address, City, State, or Zipcode" id="search_map"/>
+        <input style="display: none;" type="submit" name="search_address_submit" value="Search"
+               id="search_address_submit"/>
+        <input type="hidden" name="long" value="" id="long"/>
+        <input type="hidden" name="lat" value="" id="lat"/>
+        <a href="javascript:;" id="search_address_button">Search Address</a>
+        <a href="javascript:;" id="select_coords_button">Set Coordinates</a>
+
+        <p class="field_tip">Search by address or drag the push-pin to the desired coordinates.</p>
+
+        <p id="on_coords"><span id="on_lat"></span>, <span id="on_long"></span></p>
+    </form>
+</div>
+
+</body>
+</html>

CoordinatePicker/coordinate_picker/map.js

+var Map;
+
+(function ($) {
+
+    Map = {
+        map:null,
+        markers:[],
+        init:function (config) {
+
+            var settings = {
+                lat_selector:'#lat',
+                long_selector:'#long',
+                onComplete:false
+            };
+
+            if (window.parent.$.coordinate_picker && window.parent.$.coordinate_picker.settings) {
+                $.extend(settings, window.parent.$.coordinate_picker.settings);
+            }
+
+            //todo: save this in coockies
+            var zoom = 12; // town level
+
+            var coord_lat, coord_long;
+            // try to load coords from inputs
+            if ($(settings.long_selector, window.parent.document).length) {
+                coord_long = 0 + $(settings.long_selector, window.parent.document).attr('value');
+            }
+
+            if ($(settings.lat_selector, window.parent.document).length) {
+                coord_lat = 0 + $(settings.lat_selector, window.parent.document).attr('value');
+            }
+
+            // Kyiv Coords
+            if (coord_lat < 0.0000000001 && coord_long < 0.0000000001) {
+                coord_lat = 50.443513052458044;
+                coord_long = 30.498046875;
+                zoom = 7; // counry level
+            }
+
+
+            console.log(window.location.hash);
+            if (google.maps.ClientLocation) {
+                zoom = 12;
+                coord_lat = google.maps.ClientLocation.latitude;
+                coord_long = google.maps.ClientLocation.longitude;
+            }
+
+            var latlng = new google.maps.LatLng(coord_lat, coord_long);
+
+            var options = {
+                zoom:zoom,
+                center:latlng,
+                mapTypeId:google.maps.MapTypeId.ROADMAP
+            };
+
+            Map.map = new google.maps.Map($('#map_canvas').get(0), options);
+
+            google.maps.event.addListener(Map.map, 'dragend', Map.update_marker);
+            google.maps.event.addListener(Map.map, 'zoom_changed', Map.update_marker);
+
+
+            var geocoderService = new google.maps.Geocoder();
+            Map.add_marker(latlng);
+            Map.update();
+
+            $('#search_map').focus();
+            $('#search_map').input_hint();
+
+            $('#search_address_button').click(function () {
+                $(this).parents('form').submit();
+            });
+
+            $('#search_map_form').submit(function (e) {
+                e.preventDefault();
+                geocoderService.geocode({'address':$('#search_map').val()}, function (results, status) {
+                    if (status == google.maps.GeocoderStatus.OK) {
+
+                        var latlng = results[0].geometry.location;
+                        Map.add_marker(latlng);
+                        Map.update();
+                        Map.map.fitBounds(results[0].geometry.viewport);
+                    }
+                    else if (status == google.maps.GeocoderStatus.ZERO_RESULTS) {
+                        alert('Address not found');
+                    }
+                    else {
+                        alert('Address lookup failed');
+                    }
+                });
+
+            });
+
+            $('#select_coords_button').click(function (e) {
+                var coords = {'lat':$('#lat').val(), 'long':$('#long').val()};
+                if ($(settings.long_selector, window.parent.document).length) {
+                    $(settings.long_selector, window.parent.document).attr('value', coords.long);
+                }
+
+                if ($(settings.lat_selector, window.parent.document).length) {
+                    $(settings.lat_selector, window.parent.document).attr('value', coords.lat);
+                }
+                if ($.isFunction(settings.onComplete)) {
+                    settings.onComplete(coords);
+                }
+                // If using smodal box, close it.
+                if (window.parent.$.smodal) {
+                    window.parent.$.smodal.close();
+                }
+                // try closing this window
+                else {
+                    window.self.close();
+                }
+            });
+
+        },
+
+        add_marker:function (latlng) {
+            Map.reset_markers();
+
+            var marker = new google.maps.Marker({
+                map:Map.map,
+                position:latlng,
+                draggable:true
+            });
+
+            Map.markers.push(marker);
+            google.maps.event.addListener(marker, 'dragend', function (e) {
+                Map.map.panTo(e.latLng);
+                Map.update();
+            });
+
+            return marker;
+        },
+
+        reset_markers:function () {
+            if (Map.markers) {
+                for (i in Map.markers) {
+                    Map.markers[i].setMap(null);
+                }
+                Map.markers = [];
+            }
+        },
+
+        update_marker:function () {
+            var latlng = Map.map.getCenter();
+            Map.add_marker(latlng);
+            Map.update();
+        },
+
+        update:function () {
+            var marker = Map.markers[0];
+            var markerLatLng = marker.getPosition();
+
+            var lat = markerLatLng.lat(), lng = markerLatLng.lng();
+            $('#long').val(lng);
+            $('#lat').val(lat);
+            $('#on_long').text(lng.toFixed(3));
+            $('#on_lat').text(lat.toFixed(3));
+        }
+
+    };
+
+
+})(jQuery);
+
+jQuery(function ($) {
+    Map.init();
+});

CoordinatePicker/coordinate_picker/styles/background_search.png

Added
New image

CoordinatePicker/coordinate_picker/styles/body.png

Added
New image

CoordinatePicker/coordinate_picker/styles/button_go.png

Added
New image

CoordinatePicker/coordinate_picker/styles/button_select.png

Added
New image

CoordinatePicker/coordinate_picker/styles/map.css

+/* @group Corrdinate Selector with Google Map */
+
+* {
+    margin: 0;
+    padding: 0;
+}
+
+/* slightly enhanced, universal clearfix hack */
+
+.clearfix:after {
+    visibility: hidden;
+    display: block;
+    font-size: 0;
+    content: " ";
+    clear: both;
+    height: 0;
+}
+
+.clearfix {
+    display: inline-block;
+}
+
+/* start commented backslash hack \*/
+
+* html .clearfix {
+    height: 1%;
+}
+
+.clearfix {
+    display: block;
+}
+
+/* close commented backslash hack */
+
+img {
+    border: 0;
+}
+
+#wrapper {
+    font-family: helvetica;
+    width: 672px;
+    height: 472px;
+    padding: 14px;
+    background-color: #E5E5E7;
+}
+
+#map_canvas {
+    width: 672px;
+    height: 400px;
+}
+
+#search_map {
+    border: 0;
+    background: url('background_search.png') 0 0 no-repeat;
+    width: 348px;
+    height: 17px;
+    font-size: 15px;
+    line-height: 17px;
+    color: #aaa;
+    font-family: helvetica;
+    padding: 10px 10px 6px;
+    font-weight: bold;
+    float: left;
+}
+
+input.label {
+    color: #ddd !important;
+}
+
+#search_map_form {
+    display: block;
+    padding-top: 18px;
+    position: relative;
+    height: 60px;
+}
+
+#search_address_button {
+    display: block;
+    float: left;
+    margin: 2px 15px 0;
+    background: url('button_go.png') 0 0 no-repeat;
+    width: 99px;
+    height: 29px;
+    text-indent: -99999999px;
+
+}
+
+#select_coords_button {
+    display: block;
+    float: left;
+    position: relative;
+    margin-top: -16px;
+    background: url('button_select.png') 0 0 no-repeat;
+    width: 175px;
+    height: 64px;
+    text-indent: -99999999px;
+    z-index: 2;
+
+}
+
+#on_coords {
+    position: absolute;
+    background-color: #42ABDD;
+    width: 101px;
+    font-family: helvetica;
+    color: #fff;
+    font-weight: bold;
+    font-size: 10px;
+    text-align: center;
+    height: 18px;
+    line-height: 18px;
+    left: 453px;
+    top: 49px;
+    margin-left: 81px;
+    z-index: 1;
+}
+
+p.field_tip {
+    color: #888;
+    font-size: 11px;
+    position: absolute;
+    top: 58px;
+    left: 0;
+    padding-left: 10px;
+}
+
+/* @end */

CoordinatePicker/coordinate_picker/styles/smodal/close-button.png

Added
New image

CoordinatePicker/coordinate_picker/styles/smodal/shadow.css

+/*
+<div class="modal-overlay"></div>
+<div class="modal-window">
+	<iframe></iframe>
+	<a class="close-window"></a>
+</div>
+*/
+
+/* @group Modal Box */
+
+.modal-overlay {
+    position: fixed;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    height: 100%;
+    width: 100%;
+    margin: 0;
+    padding: 0;
+    z-index: 101;
+}
+
+.modal-window {
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    margin: 0;
+    padding: 0;
+    z-index: 102;
+    -moz-box-shadow: 0 0 90px 5px #000;
+    -webkit-box-shadow: 0 0 90px #000;
+    box-shadow: 0 0 90px #000;
+}
+
+/* @end */
+
+/* @group Modal Box IE */
+
+html.ie6 .modal-window, html.ie7 .modal-window, html.ie8 .modal-window {
+    border: 4px solid #666;
+}
+
+html.ie6 body {
+    height: 100%;
+}
+
+html.ie6 .modal-overlay {
+    position: absolute;
+    height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+}
+
+html.ie6 iframe.modal-overlay {
+    background: none;
+    opacity: 0;
+    filter: alpha(opacity = 0);
+    z-index: 100;
+}
+
+html.ie6 .modal-window {
+    position: absolute;
+    top: expression(document.documentElement.scrollTop + (document.documentElement.clientHeight / 2) + 'px');
+}
+
+html.ie6 .close-window {
+    background-image: url();
+    filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src = close-button.png, sizingMethod = crop);
+}
+
+/* @end */

CoordinatePicker/readme.md

+What is this
+===============================================
+- jQuery Coordinate Picker is a plugin that binds a click event to an element firing a modalbox with a google map that allows you to drag a pushpin to find and return specific coordinates.
+
+Requirements
+===============================================
+1.  jQuery.  Since the google maps coordinate selector is implemented as an iframe, those dependencies (google maps api v3, etc) are isolated and auto-loaded into that iframe.  
+
+Sample Usage
+===============================================
+Please see sample html files to see real world examples.
+
+```javascript
+
+var settings = {
+	
+	// Form input element selector for latitude
+	lat_selector: '#lat',
+	
+	// Form input element selector for latitude
+	long_selector: '#long',
+	
+	// Callback function that passes an object with the 2 properties (lat, long) in decimal format.
+	// data = {lat: 00.00000000000000, long: 00.00000000000000}
+	onComplete: function(data) {
+		
+	}
+
+};
+
+$('#coordinate_picker').coordinate_picker(settings);
+
+```
+
+Installation
+===============================================
+1.  Add the coordinate_picker directory to your web root or javascript directory.
+2.  Load **coordinate_picker/jquery.coordinate_picker.js** and **coordinate_picker/styles/smodal/shadow.css** in the page you want to use this plugin.
+
+Release Notes
+===============================================
+Version 0.5 - July 8 2011
+*Initial Release
+
+Version 0.51 - July 8 2011
+* Add ie specific styles to modal box because it doesn't support shadowbox css attributes.
+
+TODO
+===============================================
+* Figure out how find path of plugin without loading them after the dom is ready.
+* Add HTML5 Geolocation API
+* Add Microsite with demo links

CoordinatePicker/sample1.html

+<!DOCTYPE html>
+<!--[if lt IE 7 ]>
+<html lang="en" class="ie ie6"><![endif]-->
+<!--[if IE 7 ]>
+<html lang="en" class="ie ie7"><![endif]-->
+<!--[if IE 8 ]>
+<html lang="en" class="ie ie8"><![endif]-->
+<!--[if (gte IE 9)|!(IE)]><!-->
+<html lang="en"><!--<![endif]-->
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+    <style type="text/css" media="screen">
+        * {
+            margin: 0;
+            padding: 0;
+        }
+
+        body {
+            padding: 20px;
+            font-family: helvetica;
+            background-color: #eee;
+            color: #666;
+        }
+
+        label {
+            display: block;
+            line-height: 1.5;
+            font-weight: bold;
+        }
+
+        h1 {
+            padding-bottom: 10px;
+        }
+
+        p {
+            font-size: 12px;
+            line-height: 1.5;
+            padding-bottom: 10px;
+        }
+
+        #sample_form_wrapper {
+            padding: 20px 0;
+        }
+
+        a:link, a:visited {
+            color: #6D8BCD;
+        }
+
+        a:hover {
+            text-decoration: none;
+        }
+
+        img {
+            border: 0;
+        }
+    </style>
+
+    <title>jQuery Coordinate Picker - Sample 1</title>
+    <script src="http://code.jquery.com/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
+    <script src="coordinate_picker/jquery.coordinate_picker.js" type="text/javascript" charset="utf-8"></script>
+    <link rel="stylesheet" href="coordinate_picker/styles/smodal/shadow.css" type="text/css" media="screen"
+          charset="utf-8"/>
+
+    <script type="text/javascript" charset="utf-8">
+        jQuery(function ($) {
+            $('#coordinate_picker').coordinate_picker({
+                'lat_selector':'#lat',
+                'long_selector':'#long'
+            });
+        });
+    </script>
+</head>
+
+<body>
+
+<h1>jQuery Coordinate Picker - Sample 1</h1>
+
+<p>This sample uses the lat and long selectors parameters in the plugin to set the form fields to the coordinates
+    selected.</p>
+
+<div id="sample_form_wrapper">
+    <form method="post">
+
+        <p><a href="" id="coordinate_picker">Coordinate Picker</a></p>
+
+        <p><label for="long">Long:</label><input type="text" name="long" value="" id="long"/></p>
+
+        <p><label for="lat">Lat:</label><input type="text" name="lat" value="" id="lat"/></p>
+
+    </form>
+</div>
+
+</body>
+</html>

CoordinatePicker/sample2.html

+<!DOCTYPE html>
+<!--[if lt IE 7 ]>
+<html lang="en" class="ie ie6"><![endif]-->
+<!--[if IE 7 ]>
+<html lang="en" class="ie ie7"><![endif]-->
+<!--[if IE 8 ]>
+<html lang="en" class="ie ie8"><![endif]-->
+<!--[if (gte IE 9)|!(IE)]><!-->
+<html lang="en"><!--<![endif]-->
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+    <style type="text/css" media="screen">
+        * {
+            margin: 0;
+            padding: 0;
+        }
+
+        body {
+            padding: 20px;
+            font-family: helvetica;
+            background-color: #eee;
+            color: #666;
+        }
+
+        label {
+            display: block;
+            line-height: 1.5;
+            font-weight: bold;
+        }
+
+        h1 {
+            padding-bottom: 10px;
+        }
+
+        h2 {
+            color: #5E9AD2;
+        }
+
+        p {
+            font-size: 12px;
+            line-height: 1.5;
+            padding-bottom: 10px;
+        }
+
+        #sample_form_wrapper {
+            padding: 20px 0;
+        }
+
+        a:link, a:visited {
+            color: #6D8BCD;
+        }
+
+        a:hover {
+            text-decoration: none;
+        }
+
+        img {
+            border: 0;
+        }
+    </style>
+
+    <title>jQuery Coordinate Picker - Sample 2</title>
+    <script src="http://code.jquery.com/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
+    <script src="coordinate_picker/jquery.coordinate_picker.js" type="text/javascript" charset="utf-8"></script>
+    <link rel="stylesheet" href="coordinate_picker/styles/smodal/shadow.css" type="text/css" media="screen"
+          charset="utf-8"/>
+
+    <script type="text/javascript" charset="utf-8">
+        jQuery(function ($) {
+            $('#coordinate_picker').coordinate_picker({
+                onComplete:function (data) {
+                    // Argument will contain an object with the 2 properties (lat, long) in decimal format.
+                    // data = {lat: 00.00000000000000, long: 00.00000000000000}
+                    $('#coords_selected').html(data.lat + ' Lat, ' + data.long + ' Long')
+                }
+            });
+        });
+    </script>
+</head>
+
+<body>
+
+<h1>jQuery Coordinate Picker - Sample 2</h1>
+
+<p>This sample uses the callback method to work with the coordinates selected.</p>
+
+<div id="sample_form_wrapper">
+    <form method="post">
+
+        <p><a href="" id="coordinate_picker"><img src="coordinate_picker/styles/button_select.png" width="175"
+                                                  height="64" alt="Button Select"/></a></p>
+
+        <h2>Coordinates Selected: <span id="coords_selected">-</span></h2>
+
+    </form>
+</div>
+
+</body>
+</html>
+Coordinate picker usage instructions
+===========================
+
+1. Checkout source code to your project, for example to ext.coordinatepicker.
+2. Render inputs.
+3. Register script with widget.
+
+Example:
+
+    :::php
+    echo $form->textField($model, 'lat');
+    echo $form->textField($model,'long');
+
+    $this->widget('ext.coordinatepicker.CoordinatePicker', array(
+        'model' => $model,
+        'latitudeAttribute' => 'lat',
+        'longitudeAttribute' => 'long',
+    ));