code:
mxn.register('openlayers', {

    Mapstraction: {

        init: function(element, api){
            var me = this;
            this.maps[api] = new OpenLayers.Map(
                element.id,
                {
                    maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
                    maxResolution:156543,
                    numZoomLevels:18,
                    units:'meters',
                    projection: "EPSG:41001"
                }
            );

            this.layers['osmmapnik'] = new OpenLayers.Layer.TMS(
                'OSM Mapnik',
                [
                "http://a.tile.openstreetmap.org/",
                "http://b.tile.openstreetmap.org/",
                "http://c.tile.openstreetmap.org/"
                ],
                {
                    type:'png',
                    getURL: function (bounds) {
                        var res = this.map.getResolution();
                        var x = Math.round ((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
                        var y = Math.round ((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
                        var z = this.map.getZoom();
                        var limit = Math.pow(2, z);
                        if (y < 0 || y >= limit) {
                            return null;
                        } else {
                            x = ((x % limit) + limit) % limit;
                            var path = z + "/" + x + "/" + y + "." + this.type;
                            var url = this.url;
                            if (url instanceof Array) {
                                url = this.selectUrl(path, url);
                            }
                            return url + path;
                        }
                    },
                    displayOutsideMaxExtent: true
                }
            );

            this.layers['osm'] = new OpenLayers.Layer.TMS(
                'OSM',
                [
                "http://a.tah.openstreetmap.org/Tiles/tile.php/",
                "http://b.tah.openstreetmap.org/Tiles/tile.php/",
                "http://c.tah.openstreetmap.org/Tiles/tile.php/"
                ],
                {
                    type:'png',
                    getURL: function (bounds) {
                        var res = this.map.getResolution();
                        var x = Math.round ((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
                        var y = Math.round ((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
                        var z = this.map.getZoom();
                        var limit = Math.pow(2, z);
                        if (y < 0 || y >= limit) {
                            return null;
                        } else {
                            x = ((x % limit) + limit) % limit;
                            var path = z + "/" + x + "/" + y + "." + this.type;
                            var url = this.url;
                            if (url instanceof Array) {
                                url = this.selectUrl(path, url);
                            }
                            return url + path;
                        }
                    },
                    displayOutsideMaxExtent: true
                }
            );

            this.maps[api].addLayer(this.layers['osmmapnik']);
            this.maps[api].addLayer(this.layers['osm']);
        },

        applyOptions: function(){
            // var map = this.maps[this.api];
            // var myOptions = [];
            // if (this.options.enableDragging) {
            //     myOptions.draggable = true;
            // }
            // if (this.options.enableScrollWheelZoom){
            //     myOptions.scrollwheel = true;
            // }
            // map.setOptions(myOptions);
        },

        resizeTo: function(width, height){
            this.currentElement.style.width = width;
            this.currentElement.style.height = height;
            this.maps[this.api].updateSize();
        },

        addControls: function( args ) {
            var map = this.maps[this.api];
            // FIXME: OpenLayers has a bug removing all the controls says crschmidt
            for (var i = map.controls.length; i>1; i--) {
                map.controls[i-1].deactivate();
                map.removeControl(map.controls[i-1]);
            }
            if ( args.zoom == 'large' )      {
                map.addControl(new OpenLayers.Control.PanZoomBar());
            }
            else if ( args.zoom == 'small' ) {
                map.addControl(new OpenLayers.Control.ZoomPanel());
                if ( args.pan) {
                    map.addControl(new OpenLayers.Control.PanPanel());
                }
            }
            else {
                if ( args.pan){
                    map.addControl(new OpenLayers.Control.PanPanel());
                }
            }
            if ( args.overview ) {
                map.addControl(new OpenLayers.Control.OverviewMap());
            }
            if ( args.map_type ) {
                map.addControl(new OpenLayers.Control.LayerSwitcher());
            }
        },

        addSmallControls: function() {
            var map = this.maps[this.api];
            this.addControlsArgs.pan = false;
            this.addControlsArgs.scale = false;
            this.addControlsArgs.zoom = 'small';
            map.addControl(new OpenLayers.Control.ZoomBox());
            map.addControl(new OpenLayers.Control.LayerSwitcher({
                'ascending':false
            }));
        },

        addLargeControls: function() {
            var map = this.maps[this.api];
            map.addControl(new OpenLayers.Control.PanZoomBar());
            this.addControlsArgs.pan = true;
            this.addControlsArgs.zoom = 'large';
        },

        addMapTypeControls: function() {
            var map = this.maps[this.api];
            map.addControl( new OpenLayers.Control.LayerSwitcher({
                'ascending':false
            }) );
            this.addControlsArgs.map_type = true;
        },

        setCenterAndZoom: function(point, zoom) {
            var map = this.maps[this.api];
            var pt = point.toProprietary(this.api);
            map.setCenter(point.toProprietary(this.api), zoom);
        },

        addMarker: function(marker, old) {
            var map = this.maps[this.api];
            var pin = marker.toProprietary(this.api);
            if (!this.layers['markers']) {
                this.layers['markers'] = new OpenLayers.Layer.Markers('markers');
                map.addLayer(this.layers['markers']);
            }
            this.layers['markers'].addMarker(pin);

            return pin;
        },

        removeMarker: function(marker) {
            var map = this.maps[this.api];
            var pin = marker.toProprietary(this.api);
            this.layers['markers'].removeMarker(pin);
            pin.destroy();

        },

        removeAllMarkers: function() {
            var map = this.maps[this.api];

            // TODO: Add provider code
        },

        declutterMarkers: function(opts) {
            var map = this.maps[this.api];

            // TODO: Add provider code
        },

        addPolyline: function(polyline, old) {
            var map = this.maps[this.api];
            var pl = polyline.toProprietary(this.api);

            if (!this.layers['polylines']) {
                this.layers['polylines'] = new OpenLayers.Layer.Vector('polylines');
                map.addLayer(this.layers['polylines']);
            }
            polyline.setChild(pl);
            this.layers['polylines'].addFeatures([pl]);
            return pl;
        },

        removePolyline: function(polyline) {
            var map = this.maps[this.api];
            var pl = polyline.toProprietary(this.api);
            this.layers['polylines'].removeFeatures([pl]);
        },
        removeAllPolylines: function() {
            var olpolylines = [];
            for(var i = 0, length = this.polylines.length; i < length; i++){
                olpolylines.push(this.polylines[i].toProprietary(this.api));
            }
            if (this.layers['polylines']) this.layers['polylines'].removeFeatures(olpolylines);
        },

        getCenter: function() {
            var map = this.maps[this.api];
            pt = map.getCenter();
            return new mxn.LatLonPoint(pt.lat, pt.lon);
        },

        setCenter: function(point, options) {
            var map = this.maps[this.api];
            var pt = point.toProprietary(this.api);
            map.setCenter(pt);

        },

        setZoom: function(zoom) {
            var map = this.maps[this.api];
            map.zoomTo(zoom);
        },

        getZoom: function() {
            var map = this.maps[this.api];
            return map.zoom;
        },

        getZoomLevelForBoundingBox: function( bbox ) {
            var map = this.maps[this.api];
            // throw 'Not implemented';
            return zoom;
        },

        setMapType: function(type) {
            var map = this.maps[this.api];
            throw 'Not implemented (setMapType)';
        },

        getMapType: function() {
            var map = this.maps[this.api];
            // TODO: implement actual layer support
            return mxn.Mapstraction.ROAD;
        },

        getBounds: function () {
            var map = this.maps[this.api];
            var olbox = map.calculateBounds();
            return new mxn.BoundingBox(olbox.bottom, olbox.left, olbox.top, olbox.right);
        },

        setBounds: function(bounds){
            var map = this.maps[this.api];
            var sw = bounds.getSouthWest();
            var ne = bounds.getNorthEast();

            if(sw.lon > ne.lon) {
                sw.lon -= 360;
            }

            var obounds = new OpenLayers.Bounds();

            obounds.extend(new mxn.LatLonPoint(sw.lat,sw.lon).toProprietary(this.api));
            obounds.extend(new mxn.LatLonPoint(ne.lat,ne.lon).toProprietary(this.api));
            map.zoomToExtent(obounds);
        },

        addImageOverlay: function(id, src, opacity, west, south, east, north, oContext) {
            var map = this.maps[this.api];

            // TODO: Add provider code
        },

        setImagePosition: function(id, oContext) {
            var map = this.maps[this.api];
            var topLeftPoint; var bottomRightPoint;

            // TODO: Add provider code

            //oContext.pixels.top = ...;
            //oContext.pixels.left = ...;
            //oContext.pixels.bottom = ...;
            //oContext.pixels.right = ...;
        },

        addOverlay: function(url, autoCenterAndZoom) {
            var map = this.maps[this.api];

            // TODO: Add provider code

        },

        addTileLayer: function(tile_url, opacity, copyright_text, min_zoom, max_zoom) {
            var map = this.maps[this.api];

            // TODO: Add provider code
        },

        toggleTileLayer: function(tile_url) {
            var map = this.maps[this.api];

            // TODO: Add provider code
        },

        getPixelRatio: function() {
            var map = this.maps[this.api];

            // TODO: Add provider code
        },

        mousePosition: function(element) {
            var map = this.maps[this.api];

            // TODO: Add provider code
        }
    },

    LatLonPoint: {

        toProprietary: function() {
            var ollon = this.lon * 20037508.34 / 180;
            var ollat = Math.log(Math.tan((90 + this.lat) * Math.PI / 360)) / (Math.PI / 180);
            ollat = ollat * 20037508.34 / 180;
            return new OpenLayers.LonLat(ollon, ollat);
        },

        fromProprietary: function(olPoint) {
            var lon = (olPoint.lon / 20037508.34) * 180;
            var lat = (olPoint.lat / 20037508.34) * 180;
            lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
            this.lon = lon;
            this.lat = lat;
        }

    },

    Marker: {

        toProprietary: function() {
            var size, anchor, icon;
            if(this.iconSize) {
                size = new OpenLayers.Size(this.iconSize[0], this.iconSize[1]);
            }
            else {
                size = new OpenLayers.Size(21,25);
            }

            if(this.iconAnchor) {
                anchor = new OpenLayers.Pixel(this.iconAnchor[0], this.iconAnchor[1]);
            }
            else {
                // FIXME: hard-coding the anchor point
                anchor = new OpenLayers.Pixel(-(size.w/2), -size.h);
            }

            if(this.iconUrl) {
                icon = new OpenLayers.Icon(this.iconUrl, size, anchor);
            }
            else {
                icon = new OpenLayers.Icon('http://openlayers.org/dev/img/marker-gold.png', size, anchor);
            }
            var marker = new OpenLayers.Marker(this.location.toProprietary("openlayers"), icon);

            if(this.infoBubble) {
                var popup = new OpenLayers.Popup(null,
                    this.location.toProprietary("openlayers"),
                    new OpenLayers.Size(100,100),
                    this.infoBubble,
                    true);
                    popup.autoSize = true;
                    var theMap = this.map;
                    if(this.hover) {
                        marker.events.register("mouseover", marker, function(event) {
                            theMap.addPopup(popup);
                            popup.show();
                        });
                        marker.events.register("mouseout", marker, function(event) {
                            popup.hide();
                            theMap.removePopup(popup);
                        });
                    }
                    else {
                        var shown = false;
                        marker.events.register("mousedown", marker, function(event) {
                            if (shown) {
                                popup.hide();
                                theMap.removePopup(popup);
                                shown = false;
                            } else {
                                theMap.addPopup(popup);
                                popup.show();
                                shown = true;
                            }
                        });
                    }
                }

                if(this.hoverIconUrl) {
                    // TODO
                }

                if(this.infoDiv){
                    // TODO
                }
                return marker;
            },

        openBubble: function() {
            // TODO: Add provider code
        },

        hide: function() {
            this.proprietary_marker.setOptions({visible:false});
        },

        show: function() {
            this.proprietary_marker.setOptions({visible:true});
        },

        update: function() {
            // TODO: Add provider code
        }

    },

    Polyline: {

        toProprietary: function() {
            var olpolyline;
            var olpoints = [];
            var ring;
            var style = {
                strokeColor: this.color || "#000000",
                strokeOpacity: this.opacity || 1,
                strokeWidth: this.width || 1,
                fillColor: this.fillColor || "#000000",
                fillOpacity: this.getAttribute('fillOpacity') || 0.2
            };

            //TODO Handle closed attribute

            for (var i = 0, length = this.points.length ; i< length; i++){
                olpoint = this.points[i].toProprietary("openlayers");
                olpoints.push(new OpenLayers.Geometry.Point(olpoint.lon, olpoint.lat));
            }

            if (this.closed) {
                // a closed polygon
                ring = new OpenLayers.Geometry.LinearRing(olpoints);
            } else {
                // a line
                ring = new OpenLayers.Geometry.LineString(olpoints);
            }

            olpolyline = new OpenLayers.Feature.Vector(ring, null, style);

            return olpolyline;
        },

        show: function() {
            throw 'Not implemented';
        },

        hide: function() {
            throw 'Not implemented';
        }

    }

});


code:
mxn.register('yahoo', {

Mapstraction: {

	init: function(element,api) {
		var me = this;
		if (YMap) {
			this.maps[api] = new YMap(element);

			YEvent.Capture(this.maps[api], EventsList.MouseClick, function(event,location) {
				me.clickHandler(location.Lat, location.Lon, location, me);
				me.click.fire({'location': new mxn.LatLonPoint(location.Lat, location.Lon)});
			});
			YEvent.Capture(this.maps[api], EventsList.changeZoom, function() {
				me.moveendHandler(me);
				me.changeZoom.fire();
			});
			YEvent.Capture(this.maps[api], EventsList.endPan, function() {
				me.moveendHandler(me);
				me.endPan.fire();
			});
			YEvent.Capture(this.maps[api], EventsList.endAutoPan, function() {
				me.endPan.fire();
			});

			this.loaded[api] = true;
			me.load.fire();
		}
		else {
			alert(api + ' map script not imported');
		}
	},

	applyOptions: function(){

		/*
		if (this.options.enableDragging) {
			map.enableDragMap();
		} else {
			map.disableDragMap();
		}*/

	},

	resizeTo: function(width, height){
		this.maps[this.api].resizeTo(new YSize(width,height));
	},

	addControls: function( args ) {
		var map = this.maps[this.api];

		if (args.pan) {
			map.addPanControl();
		}
		else {
			// Yahoo doesn't check the pan control is there before trying to remove it
			// so throws an exception :(
			map.addPanControl();
			map.removePanControl();
		}

		if (args.zoom == 'large') {
			map.addZoomLong();
		}
		else if ( args.zoom == 'small' ) {
			map.addZoomShort();
		}
		else {
			map.removeZoomScale();
		}
	},

	addSmallControls: function() {
		var map = this.maps[this.api];
		map.addPanControl();
		map.addZoomShort();
		this.addControlsArgs.pan = true;
		this.addControlsArgs.zoom = 'small';
	},

	addLargeControls: function() {
		var map = this.maps[this.api];
		map.addPanControl();
		map.addZoomLong();
		this.addControlsArgs.pan = true;  // keep the controls in case of swap
		this.addControlsArgs.zoom = 'large';
	},

	addMapTypeControls: function() {
		var map = this.maps[this.api];
		map.addTypeControl();
	},

	dragging: function(on) {
		var map = this.maps[this.api];
		if (on) {
			map.enableDragMap();
		} else {
			map.disableDragMap();
		}
	},

	setCenterAndZoom: function(point, zoom) {
		var map = this.maps[this.api];
		var pt = point.toProprietary(this.api);

		var yzoom = 18 - zoom; // maybe?
        map.drawZoomAndCenter(pt,yzoom);
	},

	addMarker: function(marker, old) {
		var map = this.maps[this.api];
		var pin = marker.toProprietary(this.api);
		map.addOverlay(pin);
		YEvent.Capture(pin, EventsList.MouseClick, function() {
			marker.click.fire();
		});
		YEvent.Capture(pin, EventsList.openSmartWindow, function() {
			marker.openInfoBubble.fire();
		});
		YEvent.Capture(pin, EventsList.closeSmartWindow, function() {
			marker.closeInfoBubble.fire();
		});
		return pin;
	},

	removeMarker: function(marker) {
		var map = this.maps[this.api];
		map.removeOverlay(marker.proprietary_marker);
	},

	removeAllMarkers: function() {
		var map = this.maps[this.api];
		map.removeMarkersAll();
	},

	declutterMarkers: function(opts) {
		throw 'Not implemented';
	},

	addPolyline: function(polyline, old) {
		var map = this.maps[this.api];
		var pl = polyline.toProprietary(this.api);
		map.addOverlay(pl);
		return pl;
	},

	removePolyline: function(polyline) {
		var map = this.maps[this.api];
		map.removeOverlay(polyline.proprietary_polyline);
	},

	getCenter: function() {
		var map = this.maps[this.api];
		var pt = map.getCenterLatLon();
        var point = new mxn.LatLonPoint(pt.Lat, pt.Lon);
		return point;
	},

	setCenter: function(point, options) {
		var map = this.maps[this.api];
		var pt = point.toProprietary(this.api);
		map.panToLatLon(pt);
	},

	setZoom: function(zoom) {
		var map = this.maps[this.api];
		var yzoom = 18 - zoom; // maybe?
		map.setZoomLevel(yzoom);
	},

	getZoom: function() {
		var map = this.maps[this.api];
		return 18 - map.getZoomLevel();
	},

	getZoomLevelForBoundingBox: function( bbox ) {
		throw 'Not implemented';
	},

	setMapType: function(type) {
		var map = this.maps[this.api];

		switch(type) {
			case mxn.Mapstraction.ROAD:
				map.setMapType(YAHOO_MAP_REG);
				break;
			case mxn.Mapstraction.SATELLITE:
				map.setMapType(YAHOO_MAP_SAT);
				break;
			case mxn.Mapstraction.HYBRID:
				map.setMapType(YAHOO_MAP_HYB);
				break;
			default:
				map.setMapType(YAHOO_MAP_REG);
		}
	},

	getMapType: function() {
		var map = this.maps[this.api];
		var type = map.getCurrentMapType();
		switch(type) {
			case YAHOO_MAP_REG:
				return mxn.Mapstraction.ROAD;
			case YAHOO_MAP_SAT:
				return mxn.Mapstraction.SATELLITE;
			case YAHOO_MAP_HYB:
				return mxn.Mapstraction.HYBRID;
			default:
				return null;
		}
	},

	getBounds: function () {
		var map = this.maps[this.api];
		var ybox = map.getBoundsLatLon();
        return new mxn.BoundingBox(ybox.LatMin, ybox.LonMin, ybox.LatMax, ybox.LonMax);
	},

	setBounds: function(bounds){
		var map = this.maps[this.api];
		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();

		if(sw.lon > ne.lon) {
			sw.lon -= 360;
		}
		var center = new YGeoPoint((sw.lat + ne.lat)/2, (ne.lon + sw.lon)/2);

		var container = map.getContainerSize();
		for(var zoom = 1 ; zoom <= 17 ; zoom++){
			var sw_pix = mxn.util.convertLatLonXY_Yahoo(sw,zoom);
			var ne_pix = mxn.util.convertLatLonXY_Yahoo(ne,zoom);
			if(sw_pix.x > ne_pix.x) {
				sw_pix.x -= (1 << (26 - zoom)); //earth circumference in pixel
			}
			if(Math.abs(ne_pix.x - sw_pix.x) <= container.width
				&& Math.abs(ne_pix.y - sw_pix.y) <= container.height){
				map.drawZoomAndCenter(center, zoom); //Call drawZoomAndCenter here: OK if called multiple times anyway
				break;
			}
		}
	},

	addImageOverlay: function(id, src, opacity, west, south, east, north, oContext) {
		throw 'Not implemented';
	},

	setImagePosition: function(id) {
	   throw 'Not implemented';
	},

	addOverlay: function(url, autoCenterAndZoom) {
		var map = this.maps[this.api];
		map.addOverlay(new YGeoRSS(url));
	},

	addTileLayer: function(tile_url, opacity, copyright_text, min_zoom, max_zoom) {
		throw 'Not implemented';
	},

	toggleTileLayer: function(tile_url) {
		throw 'Not implemented';
	},

	getPixelRatio: function() {
		throw 'Not implemented';
	},

	mousePosition: function(element) {
		throw 'Not implemented';
	}

},

LatLonPoint: {

	toProprietary: function() {
		return new YGeoPoint(this.lat,this.lon);
	},

	fromProprietary: function(yahooPoint) {
		this.lat = yahooPoint.Lat;
		this.lon = yahooPoint.Lon;
	}

},

Marker: {

	toProprietary: function() {
		var ymarker, size;
		var infoBubble, event_action, infoDiv, div;

	    if(this.iconSize) {
	        size = new YSize(this.iconSize[0], this.iconSize[1]);
	    }
	    if(this.iconUrl) {
	        if(this.iconSize){
	            ymarker = new YMarker(this.location.toProprietary('yahoo'), new YImage(this.iconUrl, size));
			}
	        else {
	            ymarker = new YMarker(this.location.toProprietary('yahoo'), new YImage(this.iconUrl));
			}
	    }
	    else {
	        if(this.iconSize) {
	            ymarker = new YMarker(this.location.toProprietary('yahoo'), null, size);
			}
	        else {
	            ymarker = new YMarker(this.location.toProprietary('yahoo'));
			}
	    }

	    if(this.labelText) {
	        ymarker.addLabel(this.labelText);
	    }

	    if(this.infoBubble) {
	        infoBubble = this.infoBubble;
	        if(this.hover) {
	            event_action = EventsList.MouseOver;
	        }
	        else {
	            event_action = EventsList.MouseClick;
	        }
	        YEvent.Capture(ymarker, event_action, function() {
	            ymarker.openSmartWindow(infoBubble);
	        });

	    }

	    if(this.infoDiv) {
	        infoDiv = this.infoDiv;
	        div = this.div;
	        if(this.hover) {
	            event_action = EventsList.MouseOver;
	        }
	        else {
	            event_action = EventsList.MouseClick;
	        }
	        YEvent.Capture(ymarker, event_action, function() {
	            document.getElementById(div).innerHTML = infoDiv;
	        });
	    }

	    return ymarker;
	},

	openBubble: function() {
		var ypin = this.proprietary_marker;
        ypin.openSmartWindow(this.infoBubble);
	},

	hide: function() {
		this.proprietary_marker.hide();
	},

	show: function() {
		this.proprietary_marker.unhide();
	},

	update: function() {
		throw 'Not implemented';
	}

},

Polyline: {

	toProprietary: function() {
		var ypolyline;
	    var ypoints = [];
	    for (var i = 0, length = this.points.length ; i< length; i++){
	        ypoints.push(this.points[i].toProprietary('yahoo'));
	    }
	    ypolyline = new YPolyline(ypoints,this.color,this.width,this.opacity);
	    return ypolyline;
	},

	show: function() {
		throw 'Not implemented';
	},

	hide: function() {
		throw 'Not implemented';
	}

}

});

repo_name: ksuudilla/gnu

license: mit


code:
function scrapeNotices(user)
{
     var notices = [];
     $(".notice").each(function(){
          var notice = getNoticeFromElement($(this));
          if (user) {
               notice['user'] = user;
          } else {
               notice['user'] = getUserFromElement($(this));
          }
          if(notice['geo'])
               notices.push(notice);
     });

     return notices;
}

function scrapeUser()
{
     var avatarURL = $(".entity_profile .entity_depiction img.avatar").attr('src');
     var profileURL = $(".entity_profile .entity_nickname .url").attr('href');
     var nickname = $(".entity_profile .entity_nickname .nickname").text();

     return {
        'profile_image_url': avatarURL,
        'profile_url': profileURL,
        'screen_name': nickname
     };
}

function getNoticeFromElement(noticeElement)
{
    var notice = {};

    if(noticeElement.find(".geo").length) {
        var latlon = noticeElement.find(".geo").attr('title').split(";");
        notice['geo']={'coordinates': [
            parseFloat(latlon[0]),
            parseFloat(latlon[1])] };
    }

    notice['html'] = noticeElement.find(".e-content").html();
    notice['url'] = noticeElement.find("a.timestamp").attr('href');
    notice['created_at'] = noticeElement.find("abbr.published").text();

    return notice;
}

function getUserFromElement(noticeElement)
{
     var avatarURL = noticeElement.find("img.avatar").attr('src');
     var profileURL = noticeElement.find(".author a.url").attr('href');
     var nickname =  noticeElement.find(".author .nickname").text();

     return {
          'profile_image_url': avatarURL,
          'profile_url': profileURL,
          'screen_name': nickname
    };
}

function showMapstraction(element, notices) {
     if(element instanceof jQuery) element = element[0];
     if(! $.isArray(notices)) notices = [notices];
     var mapstraction = new mxn.Mapstraction(element, _provider);

     var minLat = 181.0;
     var maxLat = -181.0;
     var minLon = 181.0;
     var maxLon = -181.0;

     for (var i in notices)
     {
          var n = notices[i];

          var lat = n['geo']['coordinates'][0];
          var lon = n['geo']['coordinates'][1];

          if (lat < minLat) {
               minLat = lat;
          }

          if (lat > maxLat) {
               maxLat = lat;
          }

          if (lon < minLon) {
               minLon = lon;
          }

          if (lon > maxLon) {
               maxLon = lon;
          }

          pt = new mxn.LatLonPoint(lat, lon);
          mkr = new mxn.Marker(pt);

          mkr.setIcon(n['user']['profile_image_url'], [24, 24]);
          mkr.setInfoBubble('' + n['user']['screen_name'] + '' + ' ' + n['html'] +
                            '
'+ n['created_at'] + '');

          mapstraction.addMarker(mkr);
     }

     bounds = new mxn.BoundingBox(minLat, minLon, maxLat, maxLon);

     mapstraction.setBounds(bounds);
}


code:
// Update the local timeline from a Meteor server

var MeteorUpdater = function()
{
     return {

          init: function(server, port, scheme, timeline)
          {
               Meteor.callbacks["process"] = function(data) {
                    RealtimeUpdate.receive(JSON.parse(data));
               };

               Meteor.host = server;
               Meteor.port = port;
               Meteor.scheme = scheme;
               Meteor.joinChannel(timeline, 0);
               Meteor.connect();
          }
     }
}();


code: @import url(mp-screen.css);


code:
#wrap {
    margin: 0;
    padding: 0;
    min-width:0;
    max-width:100%;
    width: auto;
    border: none;
}

#header {
    width: 100%;
}

address {
    margin: 1px 0 0;
    height: 24px;
}

address img {
    float: left;
    background: #fff;
    padding: 2px 2px 2px 6px;
}

address img + .fn {
    display:block;
    margin-top: 8px;
    clear: left;
    float: left;
    color: #000;
    margin-left: 6px;
}

#site_nav_global_primary {
    width: 100%;
    padding: 2px 0;
    height: auto;
    left:0;
}

#site_nav_global_primary li {
    margin-right: 4px;
}

#site_nav_global_primary li:last-child {
    margin-right: 0px;
}

#site_nav_global_primary a {
    padding: 2px 4px;
}

#core {
    width: 100%;
    border-left: none;
    border-right: none;
}

#aside_primary_wrapper {
    background: none;
}

#content_wrapper {
    right: 0px;
    border: none;
}

#site_nav_local_views_wrapper {
    right: 0px;
    border: none;
}

#navtoggle {
    float: right;
    padding: 2px 6px;
    text-decoration: none;
}

#site_nav_local_views {
    margin-bottom: 0px;
    padding: 10px 0px 10px 6px;
    left: 0px;
    width: 100%;
    display: none;
}

#site_nav_local_views h3 {
    font-size: 1em;
    margin-bottom: 0px;
}

#site_nav_local_views li {
    margin: 0 6px 0 0;
    clear: left;
}

#site_nav_local_views li li {
    float: left;
    clear: none;
    margin: 0 10px 6px 0;
}

#login #site_nav_local_views, #register #site_nav_local_views, #openidlogin #site_nav_local_views {
    display: block;
    margin-top: 25px;
}

#login #navtoggle, #register #navtoggle, #openidlogin #navtoggle {
    display: none;
}

#login #site_nav_local_views li, #register #site_nav_local_views li, #openidlogin #site_nav_local_views li {
    float: left;
    clear: none;
    margin: 0 10px 6px 0;
}

#content {
    width: 96%;
    padding: 10px 2%;
    min-height: auto;
    left: 0px;
}

#content h1 {
    clear: left;
}

#footer {
    width: auto;
    padding: 10px 4px 4px 4px;
}

.input_forms {
    width: 102%;
    left: -2%;
    padding-left: 2%;
}

#input_form_nav li a {
    margin-right: 6px;
}

.input_form {
    clear: left;
    width: 100%;
    padding-bottom: 0px;
}

#input_form_status, #input_form_direct {
    padding-bottom: 40px;
}

.form_notice_placeholder .placeholder {
    width: 290px;
    margin-bottom: 20px;
}

.form_notice {
    float: left;
    width: 300px;
    padding: 4px 0px;
}

#form_notice-direct.form_notice {
    padding-top: 0px;
}

.form_notice textarea, #form_notice-direct.form_notice textarea {
    width: 292px;
    height: 36px;
    padding: 4px 4px 16px 4px;
    font-size: 1em;
}

.form_notice .count {
    position: absolute;
    top: 46px;
    left: 278px;
}

#form_notice-direct.form_notice .count {
    top: 76px;
    left: 278px;
}

.form_notice .error,
.form_notice .success,
.form_notice .notice-status {
    width: 285px;
}

/*input type=file no good in
iPhone/iPod Touch, Android, Opera Mini Simulator
*/

.form_notice .notice_data-attach, .form_notice .notice_data-geo_wrap label, .form_notice .notice_data-geo_wrap input {
    display:none;
}

.checkbox-wrapper {
    margin-left: 0px;
    clear: left;
    float: left;
    width: 200px;
    z-index: 2;
}

.form_notice .checkbox-wrapper {
    margin-left: 0px;
}

.checkbox-wrapper label.checkbox {
    display: none !important;
}

.checkbox-wrapper #notice_private {
    display: inline;
    margin-top: 10px;
    margin-left: 20px;
}

.form_notice .checkbox-wrapper #notice_private {
    margin-left: 0px;
}

.checkbox-wrapper:before {
    content: "Send privately?";
}

.input_form .form_settings fieldset fieldset {
    width: 300px;
}

.input_form .form_settings label {
    display: inline;
}

label[for=blog-entry-content] {
    display: none !important;
}

.input_form .form_settings li input {
    width: 292px;
}

.input_form .form_settings li textarea {
    width: 292px;
}

.bookmarkform-thumbnail {
    display: none;
}

.input_form .form_settings .submit {
    margin: 10px 0;
    clear: left;
    float: left;
}

.form_notice input.submit {
    margin-top: -45px;
    width: 80px;
}

#form_notice-direct.form_notice #notice_action-submit {
    top: 148px;
}

.threaded-replies {
    width: 80%;
}

#content .notice .threaded-replies .notice {
    width: 95%;
}

.threaded-replies .placeholder {
    margin: 10px;
    width: 92%;
}

.threaded-replies .form_notice {
    margin-bottom: 10px;
}

.threaded-replies .form_notice textarea {
    width: 220px;
}

.threaded-replies .form_notice .count {
    left: 215px;
    top: 55px;
}

.threaded-replies .form_notice #notice_action-submit {
    position: relative;
    top: 0;
    bottom: 0px;
    left: 0;
    margin-top: 10px;
}

.threaded-replies .form_notice .error,
.threaded-replies .form_notice .success,
.threaded-replies .form_notice .notice-status {
    width: 210px;
}

.form_settings fieldset {
    margin-bottom: 7px;
}

.form_settings label {
    width: auto;
    display: block;
    text-align: left;
}

.form_settings .form_data li {
    margin-bottom: 10px;
}

.form_settings .form_data textarea,
.form_settings .form_data select,
.form_settings .form_data input {
    margin-left: 0;
}

.form_settings .form_data textarea {
    width: 98%;
}

.form_settings .form_data label {
    float: none;
}

.form_settings .form_data p.form_guide {
    margin-left: 0;
}

.form_settings input.checkbox, .form_settings input.radio {
    left: 0px;
}

.form_settings label.checkbox, .form_settings label.radio {
    left: -10px;
}

.notice .addressees:before {
    content: '\003E';
}


code:
.remote-profile-options {
    position: absolute;
    z-index: 999;

    background: url(../../../theme/base/images/icons/twotone/green/admin.gif) no-repeat 8px 8px white;
    border: solid 1px #c0c0c0;

    margin-top: 32px;

    padding: 6px 16px;
    padding-left: 32px;

    border-radius: 8px;

    box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3);

    display: none;
}


code:
/**
 * modplus.js
 * (c) 2010 StatusNet, Inc
 */

$(function() {
    // Notice lists...
    $(document).on('mouseenter', '.notice .p-author', function(e) {
        var notice = $(this).closest('.notice');
        var popup = notice.find('.remote-profile-options');
        if (popup.length) {
            popup.fadeIn();
        }
    });
    $(document).on('mouseleave', '.notice', function(e) {
        var notice = $(this);
        var popup = notice.find('.remote-profile-options');
        if (popup.length) {
            popup.fadeOut();
        }
    });

    // Profile lists...
    $(document).on('mouseenter', '.profile .u-photo', function(e) {
        var profile = $(this).closest('.profile');
        var popup = profile.find('.remote-profile-options');
        if (popup.length) {
            popup.fadeIn();
        }
    });
    $(document).on('mouseleave', '.profile', function(e) {
        var profile = $(this);
        var popup = profile.find('.remote-profile-options');
        if (popup.length) {
            popup.fadeOut();
        }
    });

});


code:
Feed icon rendered from http://commons.wikimedia.org/wiki/File:Feed-icon.svg

Originally distributed by the Mozilla Foundation under a MPL/GPL/LGPL tri-license:

http://www.mozilla.org/MPL/boilerplate-1.1/mpl-tri-license-html

path: public/plugins/OStatus/images/README


code:
/*
 * StatusNet - a distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  OStatus UI interaction
 * @package   StatusNet
 * @author    Sarven Capadisli <csarven@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 * @note      Everything in here should eventually migrate over to /js/util.js's SN.
 */

SN.U.DialogBox = {
    Subscribe: function (a) {
        var f = a.parent().find('.form_settings');
        if (f.length > 0) {
            f.show();
        }
        else {
            $.ajax({
                type: 'GET',
                dataType: 'xml',
                url: a[0].href + ((a[0].href.match(/[\\?]/) === null)?'?':'&') + 'ajax=1',
                beforeSend: function (formData) {
                    a.addClass('processing');
                },
                error: function (xhr, textStatus, errorThrown) {
                    alert(errorThrown || textStatus);
                },
                success: function (data, textStatus, xhr) {
                    if (typeof($('form', data)[0]) != 'undefined') {
                        a.after(document._importNode($('form', data)[0], true));

                        var form = a.parent().find('.form_settings');

                        form
                            .addClass('dialogbox')
                            .append('<button class="close">×</button>');

                        form
                            .find('.submit')
                                .addClass('submit_dialogbox')
                                .removeClass('submit')
                                .bind('click', function () {
                                    form.addClass('processing');
                                });

                        form.find('button.close').click(function (){
                            form.hide();

                            return false;
                        });

                        form.find('#profile').focus();
                    }

                    a.removeClass('processing');
                }
            });
        }
    }
};

SN.Init.Subscribe = function () {
    $(document).on('click',
        '.entity_subscribe .entity_remote_subscribe, .entity_tag .entity_remote_tag',
        function () { SN.U.DialogBox.Subscribe($(this)); return false; });
};

$(document).ready(function () {
    SN.Init.Subscribe();

    $('.form_remote_authorize').bind('submit', function () {
            $(this).addClass(SN.C.S.Processing); return true;
        });
});


code:
#form_ostatus_connect.dialogbox .form_data label,
#form_ostatus_sub.dialogbox .form_data label {
    display: block;
    width: 100%;
    text-align: left;
}

#form_ostatus_connect.dialogbox .form_data input,
#form_ostatus_sub.dialogbox .form_data input {
    width: 90%;
    padding: 4px;
    margin: 0;
    background-color: #fff !important;
    border: 1px solid #888;
}

#form_ostatus_connect.dialogbox .form_data .form_guide,
#form_ostatus_sub.dialogbox .form_data .form_guide {
    margin-left: 0;
    background-color: #fff !important;
}

#form_ostatus_connect.dialogbox #ostatus_nickname,
#form_ostatus_sub.dialogbox #ostatus_nickname {
    display: none;
}

#form_ostatus_connect.dialogbox input.submit_dialogbox,
#form_ostatus_sub.dialogbox input.submit_dialogbox {
    padding: 4px;
}

.entity_remote_tag {
    background-position: 5px -257px;
}

.section .entity_remote_tag {
    background-position: 5px -257px;
}


code: TCPSocket = Orbited.TCPSocket;


code:
// Update the local timeline from a Orbited server

var OrbitedUpdater = function()
{
     return {

          init: function(server, port, timeline, username, password)
          {
               // set up stomp client.
               stomp = new STOMPClient();

               stomp.onmessageframe = function(frame) {
                    RealtimeUpdate.receive(JSON.parse(frame.body));
               };

               stomp.onconnectedframe = function() {
                    stomp.subscribe(timeline);
               }

               stomp.connect(server, port, username, password);
          }
     }
}();


code:
/* Poll specific styles */

.poll-block {
    float: left;
    height: 16px;
    background: #8aa;
    margin-right: 8px;
}

.poll-winner {
    background: #4af;
}

.notice div.poll-content {
    opacity: 1;
}

#poll-response-submit {
    min-width: 100px;
}


code:
/* QnA */

.question .answer-count, .qna-full-question .answer-count {
    display: block;
    clear: left;
}

.question .answer-count:before, .qna-full-question .answer-count:before {
    content: '(';
}

.question .answer-count:after, .qna-full-question .answer-count:after {
    content: ')';
}

.question .notice-answer {
    margin-left: 10px;
    padding-bottom: 10px;
}

ul.qna-dummy {
    clear: left;
    float: left;
    list-style-type: none;
    width: 458px;
    margin-left: 59px;
    padding-right: 2px;
    border-left: 3px solid #ECECF2;
    background: #fafafa;
    font-size: 1em;
}

ul.qna-dummy + ul.threaded-replies li.notice:first-child, li.notice-answer + li.notice {
    border-top: 2px dotted #eee;
    margin-top: -10px;
    padding-top: 10px;
}

.qna-dummy-placeholder input {
    margin: 10px 0px 10px 10px;
    width: 426px;
    color: #888;
    border: 1px solid #A6A6A6;
    padding: 4px 4px 4px 6px;
}

.question fieldset, .qna-full-question fieldset {
    margin: 0px;
}

.question fieldset legend, .qna-full-question fieldset legend, .answer fieldset legend {
    display: none;
}

.question label[for=qna-answer], .qna-full-question label[for=qna-answer] {
    display: none;
}

.question #qna-answer, .qna-full-question #qna-answer {
    width: 426px;
    height: 54px;
    padding: 6px 5px;
    font-size: 1.2em;
    margin-top: 10px;
    margin-bottom: 10px;
    border: 1px solid #A6A6A6;
}

.qna-full-question textarea {
    width: 508px;
}

.question p.best:before, .answer p.best:before {
    content: '[Best] ';
}

.question .question-closed {
    display: block;
    font-style: italic;
}

.question div.question-description {
    font-size: 1em;
    line-height: 1.36em;
    margin-top: 0px;
    opacity: 1;
}

.question div.answer-content, .qna-full-question div.answer-content {
    font-size: 1em;
    opacity: 1;
}

.qna-dummy-placeholder input, .question #qna-answer, .qna-full-question #qna-answer {
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
    box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2);
}

.question-description input.submit, .answer-content input.submit {
    height: auto;
    padding: 0px 10px;
    margin: 6px 0px 10px 0px;
    color:#fff;
    font-weight: bold;
    text-transform: uppercase;
    font-size: 1.1em;
    text-shadow: 0px -1px 0px rgba(0, 0, 0, 0.2);
    border: 1px solid #d7621c;
    border-radius: 4px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    background: #FB6104;
    background: -moz-linear-gradient(top, #ff9d63 0%, #fb6104 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ff9d63), color-stop(100%,#fb6104));
    background: -webkit-linear-gradient(top, #ff9d63 0%,#fb6104 100%);
    background: -o-linear-gradient(top, #ff9d63 0%,#fb6104 100%);
    background: -ms-linear-gradient(top, #ff9d63 0%,#fb6104 100%);
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff9d63', endColorstr='#fb6104',GradientType=0 );
    background: linear-gradient(top, #ff9d63 0%,#fb6104 100%);
}

#qna-answer-submit {
    min-width: 100px;
}

.question .question-description input.submit:hover, .question .answer-content input.submit:hover {
    text-shadow: 0px -1px 0px rgba(0, 0, 0, 0.6);
    background: #ff9d63;
    background: -moz-linear-gradient(top, #fb6104 0%, #fc8035 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fb6104), color-stop(100%,#fc8035));
    background: -webkit-linear-gradient(top, #fb6104 0%,#fc8035 100%);
    background: -o-linear-gradient(top, #fb6104 0%,#fc8035 100%);
    background: -ms-linear-gradient(top, #fb6104 0%,#fc8035 100%);
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fb6104', endColorstr='#fc8035',GradientType=0 );
    background: linear-gradient(top, #fb6104 0%,#fc8035 100%);
}

.question .question-description #answer-form input.submit {
    margin-top: 0px;
}

.question p.best, .answer p.best {
    background: url(../images/rosette.png) no-repeat top left;
    padding-left: 20px;
}

.question p.best:before, .answer p.best:before {
    content: none !important;
}


code:
var QnA = {

    // @fixme: Should use ID
    close: function (form, best) {
        var notice = $(form).closest('li.h-entry.notice.question');

        notice.find('input#qna-best-answer,#qna-question-close').hide();
        notice.find('textarea').hide();

        var list = notice.find('ul');

        notice.find('ul > li.notice-answer-placeholder').remove();
        notice.find('ul > li.notice-answer').remove();

        if (best) {
            var p = notice.parent().find('div.question-description > form > fieldset > p');
            if (p.length != 0) {
                p.append($('This question is closed.'));
            }
        }
    },

    init: function () {
        QnA.NoticeInlineAnswerSetup();

        $(document).on('submit', 'form.form_question_show', function () {
            QnA.close(this);
        });
        $(document).on('submit', 'form.form_answer_show', function () {
            QnA.close(this, true);
        });
    },

    /**
     * Open up a question's inline answer box.
     *
     * @param {jQuery} notice: jQuery object containing one notice
     */
    NoticeInlineAnswerTrigger: function (notice) {
        // Find the notice we're replying to...
        var id = $($('.notice_id', notice)[0]).text();
        var parentNotice = notice;

        // Find the threaded replies view we'll be adding to...
        var list = notice.closest('.notices');
        if (list.hasClass('threaded-replies')) {

            // We're replying to a reply; use reply form on the end of this list.
            // We'll add our form at the end of this; grab the root notice.
            parentNotice = list.closest('.notice');

        } else {

            // We're replying to a parent notice; pull its threaded list
            // and we'll add on the end of it. Will add if needed.
            list = $('ul.threaded-replies', notice);
        }

        // See if the form's already open...
        var answerForm = $('.qna_answer_form', list);

        var hideReplyPlaceholders = function (notice) {
            // Do we still have a dummy answer placeholder? If so get rid of
            // reply place holders for this question. If the current user hasn't
            // answered the question we want to direct her to providing an
            // answer. She can still reply by hitting the reply button if she
            // really wants to.
            var dummyAnswer = $('ul.qna-dummy', notice);
            if (dummyAnswer.length > 0) {
                notice.find('li.notice-reply-placeholder').hide();
            }
        }

        var nextStep = function () {
            var dummyAnswer = $('ul.qna-dummy', notice);
            dummyAnswer.hide();

             // Set focus...
            var text = answerForm.find('textarea');

            if (text.length == 0) {
                throw "No textarea";
            }

            text.focus();

            $('body').click(function (e) {
                var dummyAnswer = $('ul.qna-dummy', notice);
                var style = dummyAnswer.attr('style');
                var ans = $(notice).find('li.h-entry.notice.anwer', notice)
                if (ans > 0) {
                    hideReplyPlaceholders(notice);
                }

                var openAnswers = $('li.notice-answer');
                    if (openAnswers.length > 0) {
                        var target = $(e.target);
                        openAnswers.each(function () {

                            // Did we click outside this one?
                            var answerItem = $(this);
                            var parentNotice = answerItem.closest('li.notice');

                            if (answerItem.has(e.target).length == 0) {
                                var textarea = answerItem.find('.notice_data-text:first');
                                var cur = $.trim(textarea.val());
                                // Only close if there's been no edit.
                                if (cur == '' || cur == textarea.data('initialText')) {
                                    answerItem.remove();
                                    dummyAnswer.show();
                                }
                            }
                        });
                    }
                });
        };

        // See if the form's already open...
        if (answerForm.length > 0 ) {
            nextStep();
        } else {
            var placeholder = list.find('li.qna-dummy-placeholder').hide();

            // Create the answer form entry at the end
            var answerItem = $('li.notice-answer', list);

            if (answerItem.length == 0) {
                 answerItem = $('

');
                 var intermediateStep = function (formMaster) {
                    // @todo cache the form if we can (worth it?)
                    var formEl = document._importNode(formMaster, true);
                    $(formEl).data('NoticeFormSetup', true);
                    answerItem.append(formEl);
                    list.prepend(answerItem); // *before* the placeholder
                    var form = answerForm = $(formEl);
                    QnA.AnswerFormSetup(form);
                    nextStep();
                };

                if (QnA.AnswerFormMaster) {
                    // @todo if we had a cached for here's where we'd use it'
                    intermediateStep(QnA.AnswerFormMaster);
                } else {
                    // Fetch a fresh copy of the answer form over AJAX.
                    // Warning: this can have a delay, which looks bad.
                    // @fixme this fallback may or may not work
                    var url = $('#answer-action').attr('value');
                     $.get(url, {ajax: 1}, function (data, textStatus, xhr) {
                         intermediateStep($('form', data)[0]);
                     });
                 }
             }
         }
     },

    /**
     * Setup function -- DOES NOT apply immediately.
     *
     * Sets up event handlers for inline reply mini-form placeholders.
     * Uses 'live' rather than 'bind', so applies to future as well as present items.
     */
    NoticeInlineAnswerSetup: function () {

        $(document).on('focus',
            'li.qna-dummy-placeholder input.placeholder',
            function () {
                var notice = $(this).closest('li.notice');
                QnA.NoticeInlineAnswerTrigger(notice);
                return false;
            });

    },

    AnswerFormSetup: function (form) {

        form.find('textarea').focus();

        if (!form.data('NoticeFormSetup')) {
            alert('gargargar');
        }

        if (!form.data('AnswerFormSetup')) {
            //SN.U.NoticeLocationAttach(form);
            QnA.FormAnswerXHR(form);
            //SN.U.FormNoticeEnhancements(form);
            //SN.U.NoticeDataAttach(form);
            form.data('NoticeFormSetup', true);
        }
    },

   /**
     * Setup function -- DOES NOT trigger actions immediately.
     *
     * Sets up event handlers for special-cased async submission of the
     * answer-posting form, including some pre-post validation.
     *
     * @fixme geodata
     * @fixme refactor and unify with FormNoticeXHR in util.js
     *
     * @param {jQuery} form: jQuery object whose first element is a form
     *
     * @access public
     */
    FormAnswerXHR: function (form) {

        //SN.C.I.NoticeDataGeo = {};
        form.append('<input type="hidden" name="ajax" value="1"/>');

        // Make sure we don't have a mixed HTTP/HTTPS submission...
        form.attr('action', SN.U.RewriteAjaxAction(form.attr('action')));

        /**
         * Show a response feedback bit under the new-notice dialog.
         *
         * @param {String} cls: CSS class name to use ('error' or 'success')
         * @param {String} text
         * @access private
         */
        var showFeedback = function (cls, text) {
            form.append(
                $('

')
                    .addClass(cls)
                    .text(text)
            );
        };

        /**
         * Hide the previous response feedback, if any.
         */
        var removeFeedback = function () {
            form.find('.form_response').remove();
        };

        form.ajaxForm({
            dataType: 'xml',
            timeout: '60000',

            beforeSend: function (formData) {

                if (form.find('.notice_data-text:first').val() == '') {
                    form.addClass(SN.C.S.Warning);
                    return false;
                }
                form
                    .addClass(SN.C.S.Processing)
                    .find('.submit')
                        .addClass(SN.C.S.Disabled)
                        .attr(SN.C.S.Disabled, SN.C.S.Disabled);
                return true;
            },
            error: function (xhr, textStatus, errorThrown) {
                form
                    .removeClass(SN.C.S.Processing)
                    .find('.submit')
                        .removeClass(SN.C.S.Disabled)
                        .removeAttr(SN.C.S.Disabled, SN.C.S.Disabled);
                removeFeedback();
                if (textStatus == 'timeout') {
                    // @fixme i18n
                    showFeedback('error', 'Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.');
                }
                else {
                    var response = SN.U.GetResponseXML(xhr);
                    if ($('.'+SN.C.S.Error, response).length > 0) {
                        form.append(document._importNode($('.'+SN.C.S.Error, response)[0], true));
                    }
                    else {
                        if (parseInt(xhr.status) === 0 || jQuery.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) >= 0) {
                            form
                                .resetForm()
                                .find('.attach-status').remove();
                            SN.U.FormNoticeEnhancements(form);
                        }
                        else {
                            // @fixme i18n
                            showFeedback('error', '(Sorry! We had trouble sending your notice ('+xhr.status+' '+xhr.statusText+'). Please report the problem to the site administrator if this happens again.');
                        }
                    }
                }
            },
            success: function (data, textStatus) {

                removeFeedback();
                var errorResult = $('#'+SN.C.S.Error, data);
                if (errorResult.length > 0) {
                    showFeedback('error', errorResult.text());
                }
                else {

                    // New notice post was successful. If on our timeline, show it!
                    var notice = document._importNode($('li', data)[0], true);
                    var notices = $('#notices_primary .notices:first');
                    var answerItem = form.closest('li.notice-answer');
                    var questionItem = form.closest('li.question');

                    var dummyAnswer = form.find('ul.qna-dummy', questionItem).remove();
                    if (answerItem.length > 0) {

                    // If this is an inline answer, remove the form...
                    var list = form.closest('.threaded-replies');

                    // if the inserted notice's parent question needs it give it a placeholder
                    var ans = questionItem.find('ul > li.h-entry.notice.answer');
                    if (ans.length == 0) {
                        SN.U.NoticeInlineReplyPlaceholder(questionItem);
                    }

                    var id = $(notice).attr('id');
                    if ($("#"+id).length == 0) {
                        $(notice).insertBefore(answerItem);
                            answerItem.remove();
                        } else {
                            // NOP
                            // Realtime came through before us...
                        }

                    } else if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) {

                        // Not a reply. If on our timeline, show it at the
                        if ($('#'+notice.id).length === 0) {
                            var notice_irt_value = form.find('#inreplyto').val();
                            var notice_irt = '#notices_primary #notice-'+notice_irt_value;
                            if($('body')[0].id == 'conversation') {
                                if(notice_irt_value.length > 0 && $(notice_irt+' .notices').length < 1) {
                                    $(notice_irt).append('

');
                                }
                                $($(notice_irt+' .notices')[0]).append(notice);
                            }
                            else {
                                notices.prepend(notice);
                            }
                            $('#'+notice.id)
                                .css({display:'none'})
                                .fadeIn(2500);
                        }

                        // realtime injected the notice first

                    } else {
                        // Not on a timeline that this belongs on?
                        // Just show a success message.
                        // @fixme inline
                        showFeedback('success', $('title', data).text());
                    }
                }
            },
            complete: function (xhr, textStatus) {
                form
                    .removeClass(SN.C.S.Processing)
                    .find('.submit')
                        .removeAttr(SN.C.S.Disabled)
                        .removeClass(SN.C.S.Disabled);
            }
        });
    }
};

$(document).ready(function () {
    QnA.init();
});


code:
.realtime-popup address {
display:none;
}

.realtime-popup #content {
width:93.5%;
}

.realtime-popup #form_notice {
margin:18px 0 18px 1.795%;
width:93%;
max-width:451px;
}

.realtime-popup #form_notice label[for=notice_data-text],
.realtime-popup h1 {
display:none;
}

.realtime-popup #form_notice label.notice_data-attach,
.realtime-popup #form_notice input.notice_data-attach,
.realtime-popup #form_notice label.notice_data-geo {
top:0;
}

.realtime-popup #form_notice input.notice_data-attach {
left:auto;
right:0;
}

.realtime-popup .entity_profile {
width:70%;
}
.realtime-popup .entity_actions {
margin-left:1%;
}

#notices_primary {
position:relative;
}

#realtime_actions {
position: absolute;
top: -20px;
right: 0;
margin: 0 0 11px 0;
}

#realtime_actions li {
margin-left: 18px;
list-style-type: none;
float: left;
}

#realtime_actions button {
width: 16px;
height: 16px;
display: block;
border: none;
cursor: pointer;
text-indent: -9999px;
float: left;
}

#realtime_play {
margin-left: 4px;
}

#queued_counter {
float:left;
line-height:1.2;
}

#showstream #notices_primary {
margin-top: 18px;
}


code:
/*
 * StatusNet - a distributed open-source microblogging tool
 * Copyright (C) 2009-2011, StatusNet, Inc.
 *
 * Add a notice encoded as JSON into the current timeline
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Plugin
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@status.net>
 * @copyright 2009-2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

/**
 * This is the UI portion of the Realtime plugin base class, handling
 * queueing up and displaying of notices that have been received through
 * other code in one of the subclassed plugin implementations such as
 * Meteor or Orbited.
 *
 * Notices are passed in as JSON objects formatted per the Twitter-compatible
 * API.
 *
 * @todo Currently we duplicate a lot of formatting and layout code from
 *       the PHP side of StatusNet, which makes it very difficult to maintain
 *       this package. Internationalization as well as newer features such
 *       as location data, customized source links for OStatus profiles,
 *       and image thumbnails are not yet supported in Realtime yet because
 *       they have not been implemented here.
 */
RealtimeUpdate = {
     _userid: 0,
     _showurl: '',
     _keepaliveurl: '',
     _closeurl: '',
     _updatecounter: 0,
     _maxnotices: 50,
     _windowhasfocus: true,
     _documenttitle: '',
     _paused:false,
     _queuedNotices:[],

     /**
      * Initialize the Realtime plugin UI on a page with a timeline view.
      *
      * This function is called from a JS fragment inserted by the PHP side
      * of the Realtime plugin, and provides us with base information
      * needed to build a near-replica of StatusNet's NoticeListItem output.
      *
      * Once the UI is initialized, a plugin subclass will need to actually
      * feed data into the RealtimeUpdate object!
      *
      * @param {int} userid: local profile ID of the currently logged-in user
      * @param {String} showurl: URL for shownotice action, used when fetching formatting notices.
      *                            This URL contains a stub value of 0000000000 which will be replaced with the notice ID.
      *
      * @access public
      */
     init: function(userid, showurl)
     {
        RealtimeUpdate._userid = userid;
        RealtimeUpdate._showurl = showurl;

        RealtimeUpdate._documenttitle = document.title;

        $(window).bind('focus', function() {
          RealtimeUpdate._windowhasfocus = true;

          // Clear the counter on the window title when we focus in.
          RealtimeUpdate._updatecounter = 0;
          RealtimeUpdate.removeWindowCounter();
        });

        $(window).bind('blur', function() {
          $('#notices_primary .notice').removeClass('mark-top');

          $('#notices_primary .notice:first').addClass('mark-top');

          // While we're in the background, received messages will increment
          // a counter that we put on the window title. This will cause some
          // browsers to also flash or mark the tab or window title bar until
          // you seek attention (eg Firefox 4 pinned app tabs).
          RealtimeUpdate._windowhasfocus = false;

          return false;
        });
     },

     /**
      * Accept a notice in a Twitter-API JSON style and either show it
      * or queue it up, depending on whether the realtime display is
      * active.
      *
      * The meat of a Realtime plugin subclass is to provide a substrate
      * transport to receive data and shove it into this function. :)
      *
      * Note that the JSON data is extended from the standard API return
      * with additional fields added by RealtimePlugin's PHP code.
      *
      * @param {Object} data: extended JSON API-formatted notice
      *
      * @access public
      */
     receive: function(data)
     {
          if (RealtimeUpdate.isNoticeVisible(data.id)) {
              // Probably posted by the user in this window, and so already
              // shown by the AJAX form handler. Ignore it.
              return;
          }
          if (RealtimeUpdate._paused === false) {
              RealtimeUpdate.purgeLastNoticeItem();

              RealtimeUpdate.insertNoticeItem(data);
          }
          else {
              RealtimeUpdate._queuedNotices.push(data);

              RealtimeUpdate.updateQueuedCounter();
          }

          RealtimeUpdate.updateWindowCounter();
     },

     /**
      * Add a visible representation of the given notice at the top of
      * the current timeline.
      *
      * If the notice is already in the timeline, nothing will be added.
      *
      * @param {Object} data: extended JSON API-formatted notice
      *
      * @fixme while core UI JS code is used to activate the AJAX UI controls,
      *        the actual production of HTML (in makeNoticeItem and its subs)
      *        duplicates core code without plugin hook points or i18n support.
      *
      * @access private
      */
     insertNoticeItem: function(data) {
        // Don't add it if it already exists
        if (RealtimeUpdate.isNoticeVisible(data.id)) {
            return;
        }

        RealtimeUpdate.makeNoticeItem(data, function(noticeItem) {
            // Check again in case it got shown while we were waiting for data...
            if (RealtimeUpdate.isNoticeVisible(data.id)) {
                return;
            }
            var noticeItemID = $(noticeItem).attr('id');

            var list = $("#notices_primary .notices:first")
            var prepend = true;

            var threaded = list.hasClass('threaded-notices');
            if (threaded && data.in_reply_to_status_id) {
                // aho!
                var parent = $('#notice-' + data.in_reply_to_status_id);
                if (parent.length == 0) {
                    // @todo fetch the original, insert it, and finish the rest
                } else {
                    // Check the parent notice to make sure it's not a reply itself.
                    // If so, use it's parent as the parent.
                    var parentList = parent.closest('.notices');
                    if (parentList.hasClass('threaded-replies')) {
                        parent = parentList.closest('.notice');
                    }
                    list = parent.find('.threaded-replies');
                    if (list.length == 0) {
                        list = $('

');
                        parent.append(list);
                        SN.U.NoticeInlineReplyPlaceholder(parent);
                    }
                    prepend = false;
                }
            }

            var newNotice = $(noticeItem);
            if (prepend) {
                list.prepend(newNotice);
            } else {
                var placeholder = list.find('li.notice-reply-placeholder')
                if (placeholder.length > 0) {
                    newNotice.insertBefore(placeholder)
                } else {
                    newNotice.appendTo(list);
                }
            }
            newNotice.css({display:"none"}).fadeIn(1000);

            SN.U.NoticeReplyTo($('#'+noticeItemID));
            SN.U.NoticeWithAttachment($('#'+noticeItemID));
        });
     },

     /**
      * Check if the given notice is visible in the timeline currently.
      * Used to avoid duplicate processing of notices that have been
      * displayed by other means.
      *
      * @param {number} id: notice ID to check
      *
      * @return boolean
      *
      * @access private
      */
     isNoticeVisible: function(id) {
        return ($("#notice-"+id).length > 0);
     },

     /**
      * Trims a notice off the end of the timeline if we have more than the
      * maximum number of notices visible.
      *
      * @access private
      */
     purgeLastNoticeItem: function() {
        if ($('#notices_primary .notice').length > RealtimeUpdate._maxnotices) {
            $("#notices_primary .notice:last").remove();
        }
     },

     /**
      * If the window/tab is in background, increment the counter of newly
      * received notices and append it onto the window title.
      *
      * Has no effect if the window is in foreground.
      *
      * @access private
      */
     updateWindowCounter: function() {
          if (RealtimeUpdate._windowhasfocus === false) {
              RealtimeUpdate._updatecounter += 1;
              document.title = '('+RealtimeUpdate._updatecounter+') ' + RealtimeUpdate._documenttitle;
          }
     },

     /**
      * Clear the background update counter from the window title.
      *
      * @access private
      *
      * @fixme could interfere with anything else trying similar tricks
      */
     removeWindowCounter: function() {
          document.title = RealtimeUpdate._documenttitle;
     },

     /**
      * Builds a notice HTML block from JSON API-style data;
      * loads data from server, so runs async.
      *
      * @param {Object} data: extended JSON API-formatted notice
      * @param {function} callback: function(DOMNode) to receive new code
      *
      * @access private
      */
     makeNoticeItem: function(data, callback)
     {
         var url = RealtimeUpdate._showurl.replace('0000000000', data.id);
         $.get(url, {ajax: 1}, function(data, textStatus, xhr) {
             var notice = $('li.notice:first', data);
             if (notice.length) {
                 var node = document._importNode(notice[0], true);
                 callback(node);
             }
         });
     },

     /**
      * Creates a favorite button.
      *
      * @param {number} id: notice ID to work with
      * @param {String} session_key: session token for form CSRF protection
      * @return {String} HTML fragment
      *
      * @fixme this replicates core StatusNet code, making maintenance harder
      * @fixme sloppy HTML building (raw concat without escaping)
      * @fixme no i18n support
      *
      * @access private
      */
     makeFavoriteForm: function(id, session_key)
     {
          var ff;

          ff = "<form id=\"favor-"+id+"\" class=\"form_favor\" method=\"post\" action=\""+RealtimeUpdate._favorurl+"\">"+
                "<fieldset>"+
               "<legend>Favor this notice</legend>"+
               "<input name=\"token\" type=\"hidden\" id=\"token-"+id+"\" value=\""+session_key+"\"/>"+
               "<input name=\"notice\" type=\"hidden\" id=\"notice-n"+id+"\" value=\""+id+"\"/>"+
               "<input type=\"submit\" id=\"favor-submit-"+id+"\" name=\"favor-submit-"+id+"\" class=\"submit\" value=\"Favor\" title=\"Favor this notice\"/>"+
                "</fieldset>"+
               "</form>";
          return ff;
     },

     /**
      * Creates a reply button.
      *
      * @param {number} id: notice ID to work with
      * @param {String} nickname: nick of the user to whom we are replying
      * @return {String} HTML fragment
      *
      * @fixme this replicates core StatusNet code, making maintenance harder
      * @fixme sloppy HTML building (raw concat without escaping)
      * @fixme no i18n support
      *
      * @access private
      */
     makeReplyLink: function(id, nickname)
     {
          var rl;
          rl = "Reply "+id+"";
          return rl;
     },

     /**
      * Creates a repeat button.
      *
      * @param {number} id: notice ID to work with
      * @param {String} session_key: session token for form CSRF protection
      * @return {String} HTML fragment
      *
      * @fixme this replicates core StatusNet code, making maintenance harder
      * @fixme sloppy HTML building (raw concat without escaping)
      * @fixme no i18n support
      *
      * @access private
      */
     makeRepeatForm: function(id, session_key)
     {
          var rf;
          rf = "<form id=\"repeat-"+id+"\" class=\"form_repeat\" method=\"post\" action=\""+RealtimeUpdate._repeaturl+"\">"+
               "<fieldset>"+
               "<legend>Repeat this notice?</legend>"+
               "<input name=\"token\" type=\"hidden\" id=\"token-"+id+"\" value=\""+session_key+"\"/>"+
               "<input name=\"notice\" type=\"hidden\" id=\"notice-"+id+"\" value=\""+id+"\"/>"+
               "<input type=\"submit\" id=\"repeat-submit-"+id+"\" name=\"repeat-submit-"+id+"\" class=\"submit\" value=\"Yes\" title=\"Repeat this notice\"/>"+
               "</fieldset>"+
               "</form>";

          return rf;
     },

     /**
      * Creates a delete button.
      *
      * @param {number} id: notice ID to create a delete link for
      * @return {String} HTML fragment
      *
      * @fixme this replicates core StatusNet code, making maintenance harder
      * @fixme sloppy HTML building (raw concat without escaping)
      * @fixme no i18n support
      *
      * @access private
      */
     makeDeleteLink: function(id)
     {
          var dl, delurl;
          delurl = RealtimeUpdate._deleteurl.replace("0000000000", id);

          dl = "Delete";

          return dl;
     },

     /**
      * Adds a control widget at the top of the timeline view, containing
      * pause/play and popup buttons.
      *
      * @param {String} url: full URL to the popup window variant of this timeline page
      * @param {String} timeline: string key for the timeline (eg 'public' or 'evan-all')
      * @param {String} path: URL to the base directory containing the Realtime plugin,
      *                       used to fetch resources if needed.
      *
      * @todo timeline and path parameters are unused and probably should be removed.
      *
      * @access private
      */
    initActions: function(url, timeline, path, keepaliveurl, closeurl)
     {
        $('#notices_primary').prepend('

');

        RealtimeUpdate._pluginPath = path;
        RealtimeUpdate._keepaliveurl = keepaliveurl;
        RealtimeUpdate._closeurl = closeurl;

	 // On unload, let the server know we're no longer listening
         $(window).unload(function() {
            $.ajax({
                type: 'POST',
                url: RealtimeUpdate._closeurl});
	 });

	setInterval(function() {
            $.ajax({
                type: 'POST',
                url: RealtimeUpdate._keepaliveurl});

	}, 15 * 60 * 1000 ); // every 15 min; timeout in 30 min

        RealtimeUpdate.initPlayPause();
        RealtimeUpdate.initAddPopup(url, timeline, RealtimeUpdate._pluginPath);
     },

     /**
      * Initialize the state of the play/pause controls.
      *
      * If the browser supports the localStorage interface, we'll attempt
      * to retrieve a pause state from there; otherwise we default to paused.
      *
      * @access private
      */
     initPlayPause: function()
     {
        if (typeof(localStorage) == 'undefined') {
            RealtimeUpdate.showPause();
        }
        else {
            if (localStorage.getItem('RealtimeUpdate_paused') === 'true') {
                RealtimeUpdate.showPlay();
            }
            else {
                RealtimeUpdate.showPause();
            }
        }
     },

     /**
      * Switch the realtime UI into paused state.
      * Uses SN.msg i18n system for the button label and tooltip.
      *
      * State will be saved and re-used next time if the browser supports
      * the localStorage interface (via setPause).
      *
      * @access private
      */
     showPause: function()
     {
        RealtimeUpdate.setPause(false);
        RealtimeUpdate.showQueuedNotices();
        RealtimeUpdate.addNoticesHover();

        $('#realtime_playpause').remove();
        $('#realtime_actions').prepend('
<button id="realtime_pause" class="pause"></button>
');
        $('#realtime_pause').text(SN.msg('realtime_pause'))
                            .attr('title', SN.msg('realtime_pause_tooltip'))
                            .bind('click', function() {
            RealtimeUpdate.removeNoticesHover();
            RealtimeUpdate.showPlay();
            return false;
        });
     },

     /**
      * Switch the realtime UI into play state.
      * Uses SN.msg i18n system for the button label and tooltip.
      *
      * State will be saved and re-used next time if the browser supports
      * the localStorage interface (via setPause).
      *
      * @access private
      */
     showPlay: function()
     {
        RealtimeUpdate.setPause(true);
        $('#realtime_playpause').remove();
        $('#realtime_actions').prepend('
 <button id="realtime_play" class="play"></button>
');
        $('#realtime_play').text(SN.msg('realtime_play'))
                           .attr('title', SN.msg('realtime_play_tooltip'))
                           .bind('click', function() {
            RealtimeUpdate.showPause();
            return false;
        });
     },

     /**
      * Update the internal pause/play state.
      * Do not call directly; use showPause() and showPlay().
      *
      * State will be saved and re-used next time if the browser supports
      * the localStorage interface.
      *
      * @param {boolean} state: true = paused, false = not paused
      *
      * @access private
      */
     setPause: function(state)
     {
        RealtimeUpdate._paused = state;
        if (typeof(localStorage) != 'undefined') {
            localStorage.setItem('RealtimeUpdate_paused', RealtimeUpdate._paused);
        }
     },

     /**
      * Go through notices we have previously received while paused,
      * dumping them into the timeline view.
      *
      * @fixme long timelines are not trimmed here as they are for things received while not paused
      *
      * @access private
      */
     showQueuedNotices: function()
     {
        $.each(RealtimeUpdate._queuedNotices, function(i, n) {
            RealtimeUpdate.insertNoticeItem(n);
        });

        RealtimeUpdate._queuedNotices = [];

        RealtimeUpdate.removeQueuedCounter();
     },

     /**
      * Update the Realtime widget control's counter of queued notices to show
      * the current count. This will be called after receiving and queueing
      * a notice while paused.
      *
      * @access private
      */
     updateQueuedCounter: function()
     {
        $('#realtime_playpause #queued_counter').html('('+RealtimeUpdate._queuedNotices.length+')');
     },

     /**
      * Clear the Realtime widget control's counter of queued notices.
      *
      * @access private
      */
     removeQueuedCounter: function()
     {
        $('#realtime_playpause #queued_counter').empty();
     },

     /**
      * Set up event handlers on the timeline view to automatically pause
      * when the mouse is over the timeline, as this indicates the user's
      * desire to interact with the UI. (Which is hard to do when it's moving!)
      *
      * @access private
      */
     addNoticesHover: function()
     {
        $('#notices_primary .notices').hover(
            function() {
                if (RealtimeUpdate._paused === false) {
                    RealtimeUpdate.showPlay();
                }
            },
            function() {
                if (RealtimeUpdate._paused === true) {
                    RealtimeUpdate.showPause();
                }
            }
        );
     },

     /**
      * Tear down event handlers on the timeline view to automatically pause
      * when the mouse is over the timeline.
      *
      * @fixme this appears to remove *ALL* event handlers from the timeline,
      *        which assumes that nobody else is adding any event handlers.
      *        Sloppy -- we should only remove the ones we add.
      *
      * @access private
      */
     removeNoticesHover: function()
     {
        $('#notices_primary .notices').unbind();
     },

     /**
      * UI initialization, to be called from Realtime plugin code on regular
      * timeline pages.
      *
      * Adds a button to the control widget at the top of the timeline view,
      * allowing creation of a popup window with a more compact real-time
      * view of the current timeline.
      *
      * @param {String} url: full URL to the popup window variant of this timeline page
      * @param {String} timeline: string key for the timeline (eg 'public' or 'evan-all')
      * @param {String} path: URL to the base directory containing the Realtime plugin,
      *                       used to fetch resources if needed.
      *
      * @todo timeline and path parameters are unused and probably should be removed.
      *
      * @access public
      */
     initAddPopup: function(url, timeline, path)
     {
         $('#realtime_timeline').append('<button id="realtime_popup"></button>');
         $('#realtime_popup').text(SN.msg('realtime_popup'))
                             .attr('title', SN.msg('realtime_popup_tooltip'))
                             .bind('click', function() {
                window.open(url,
                         '',
                         'toolbar=no,resizable=yes,scrollbars=yes,status=no,menubar=no,personalbar=no,location=no,width=500,height=550');

             return false;
         });
     },

     /**
      * UI initialization, to be called from Realtime plugin code on popup
      * compact timeline pages.
      *
      * Sets up links in notices to open in a new window.
      *
      * @fixme fails to do the same for UI links like context view which will
      *        look bad in the tiny chromeless window.
      *
      * @access public
      */
     initPopupWindow: function()
     {
         $('.notices .entry-title a, .notices .e-content a').bind('click', function() {
            window.open(this.href, '');

            return false;
         });

         $('#showstream .entity_profile').css({'width':'69%'});
     }
}


code:
window.buildAttachmentHTML = function(attachments){
	var attachmentHTML = '';
	var oembedHTML = '';
	var quotedNotices = [];
	var attachmentNum = 0;
	var oembedNum = 0;
	var urlsToHide = [];
	if(typeof attachments != "undefined") {
		$.each(attachments, function(){

			// quoted notices
			if(typeof this.quoted_notice != 'undefined') {

				var quotedContent = this.quoted_notice.content;

				// quoted notice's attachments' thumb urls
				var quotedAttachmentsHTML = '';
				var quotedAttachmentsHTMLbefore = '';
				var quotedAttachmentsHTMLafter = '';
				if(typeof this.quoted_notice.attachments != 'undefined' && this.quoted_notice.attachments.length > 0) {
					quotedAttachmentsHTML += '
'
					$.each(this.quoted_notice.attachments,function(k,qAttach){
						quotedAttachmentsHTML += '

';
						// remove attachment string from content
						quotedContent = quotedContent.split(window.siteInstanceURL + 'attachment/' + qAttach.attachment_id).join('');
						});
					quotedAttachmentsHTML += '
';

					// if there is only one attachment, it goes before, otherwise after
					if(this.quoted_notice.attachments.length == 1) {
						quotedAttachmentsHTMLbefore = quotedAttachmentsHTML;
						}
					else {
						quotedAttachmentsHTMLafter = quotedAttachmentsHTML;
						}
					}

				var quotedNoticeHTML = quotedAttachmentsHTMLbefore + '\

\
											' + this.quoted_notice.fullname + '\
											' + this.quoted_notice.nickname + '\

\

' + $.trim(quotedContent) + '
\
										' + quotedAttachmentsHTMLafter;

				quotedNotices.push({
					url: this.url,
					html: quotedNoticeHTML,
					href: window.siteInstanceURL + 'notice/' + this.quoted_notice.id,
					class:'quoted-notice'
					});
				}

			// if we have Twitter oembed data, we add is as quotes
			else if(typeof this.oembed != 'undefined'
			&& this.oembed !== false
			&& this.oembed.provider == 'Twitter') {

				var twitterHTML =  '
\
										' + this.oembed.author_name + '\
										' + this.oembed.title + '\

\

' + this.oembed.oembedHTML + '
\

\
										' + this.oembed.provider + '\

';
				quotedNotices.push({
					url: this.url,
					html: twitterHTML,
					href: this.url,
					class:'oembed-item'
					});
				}
			// if we have other oembed data (but not for photos and youtube, we handle those later)
			else if(typeof this.oembed != 'undefined'
			&& this.oembed !== false
			&& this.oembed.title !== null
			&& this.oembed.provider != 'YouTube'
			&& this.oembed.provider != 'Vimeo'
			&& this.oembed.type != 'photo') {

				var oembedImage = '';
				// only local images
				if(typeof this.thumb_url != 'undefined'
				&& this.thumb_url !== null
				&& isLocalURL(this.thumb_url)) {
					oembedImage = '

';
					}

				var oembedBody = '';

				// don't add body if html it's too similar (80%) to the title (wordpress does this..)
				if(this.oembed.oembedHTML !== null
				&& this.oembed.oembedHTML.length > 0) {
					if(this.oembed.oembedHTML.length > 200) {
						this.oembed.oembedHTML = this.oembed.oembedHTML.substring(0,200) + 'â€¦';
						}
					if(stringSimilarity(this.oembed.oembedHTML,this.oembed.title.substring(0,200)) < 80) {
						oembedBody = this.oembed.oembedHTML;
						}
					}

				if(this.oembed.provider === null) {
					var oembedProvider = this.url;
					var oembedProviderURL = '';
					}
				else {
					var oembedProvider = this.oembed.provider;
					var oembedProviderURL = removeProtocolFromUrl(this.oembed.provider_url);
					// remove trailing /
					if(oembedProviderURL.slice(-1) == '/') {
						oembedProviderURL = oembedProviderURL.slice(0,-1);
						}
					}

				// If the oembed data is generated by Qvitter, we know a better way of showing the title
				var oembedTitle = this.oembed.title;
				var oembedTitleHTML = '' + oembedTitle + '';
				if(oembedTitle.slice(-10) == ' (Qvitter)') {
					var oembedTimePosted = parseTwitterLongDate(oembedTitle.slice(0,-10));
					var oembedGNUsocialUsername = this.oembed.author_name.substring(this.oembed.author_name.lastIndexOf('(')+1,this.oembed.author_name.lastIndexOf(')'));
					var oembedGNUsocialFullname = this.oembed.author_name.slice(0,-(oembedGNUsocialUsername.length+3));
					oembedTitleHTML =  '' + oembedGNUsocialFullname + '\
										@' + oembedGNUsocialUsername + '';
				}

				oembedHTML += '\
									' + oembedImage + '\

\
										' + oembedTitleHTML + '\

\

' + oembedBody + '
\

\
										' + oembedProvider + '\
										' + oembedProviderURL + '\

\
								 ';
				oembedNum++;
				}
			// if there's a local thumb_url we assume this is a image or video
			else if(typeof this.thumb_url != 'undefined'
			&& this.thumb_url !== null
			&& isLocalURL(this.thumb_url)) {
				var bigThumbW = 1000;
				var bigThumbH = 3000;
				if(bigThumbW > window.siteMaxThumbnailSize) {
					bigThumbW = window.siteMaxThumbnailSize;
					}
				if(bigThumbH > window.siteMaxThumbnailSize) {
					bigThumbH = window.siteMaxThumbnailSize;
					}

				// very long landscape images should not have background-size:cover
				var noCoverClass='';
				if(this.width/this.height > 2) {
					noCoverClass=' no-cover';
					}

				// play button for videos and animated gifs
				var playButtonClass = '';
				if(typeof this.animated != 'undefined' && this.animated === true
				|| (this.url.indexOf('://www.youtube.com') > -1 || this.url.indexOf('://youtu.be') > -1)
				|| this.url.indexOf('://vimeo.com') > -1) {
					playButtonClass = ' play-button';
					}

				// gif-class
				var animatedGifClass = '';
				if(typeof this.animated != 'undefined' && this.animated === true) {
					var animatedGifClass = ' animated-gif';
					}

				// animated gifs always get default small non-animated thumbnail
				if(this.animated === true) {
					var img_url = this.thumb_url;
					}
				// if no dimensions are set, go with default thumb
				else if(this.width === null && this.height === null) {
					var img_url = this.thumb_url;
					}
				// large images get large thumbnail
				else if(this.width > 1000) {
					var img_url = this.large_thumb_url;
					}
				// no thumbnails for small local images
				else if (this.url.indexOf(window.siteInstanceURL) === 0) {
					var img_url = this.url;
					}
				// small thumbnail for small remote images
				else {
					var img_url = this.thumb_url;
					}

				var urlToHide = window.siteInstanceURL + 'attachment/' + this.id;

				attachmentHTML += '';
				urlsToHide.push(urlToHide); // hide this attachment url from the queet text
				attachmentNum++;
				}
			else if (this.mimetype == 'image/svg+xml') {
				var urlToHide = window.siteInstanceURL + 'attachment/' + this.id;
				attachmentHTML += '';
				urlsToHide.push(urlToHide); // hide this attachment url from the queet text
				attachmentNum++;
				}
			});
		}
	return { html: '
' + oembedHTML + '

' + attachmentHTML + '
',
			urlsToHide: urlsToHide,
			quotedNotices: quotedNotices
		};
	}

window.sensitiveContentOriginalBuildQueetHtml = window.buildQueetHtml;

window.buildQueetHtml = function(obj, idInStream, extraClasses, requeeted_by, isConversation) {
        //add tags to json if they don't exit
        if (obj.tags && obj.tags.length > 0) {
                for (var tagI = 0; tagI < obj.tags.length; ++tagI) {
                        extraClasses += (' data-tag-' + obj.tags[tagI]);
                        if (window.loggedIn.hide_sensitive && obj.tags[tagI] === 'nsfw') extraClasses += ' sensitive-notice';
                }
        }

        return window.sensitiveContentOriginalBuildQueetHtml(obj, idInStream, extraClasses, requeeted_by, isConversation);
}


code:
icon-sharing.png is from http://www.openshareicons.com/

Shareaholic has made the Open Share Icon freely available for use by others under the
Creative Commons Attribution-Share Alike 3.0 Unported License.

icon-twitter.png is from http://twitter.com/favicon.ico and distributed under fair use
icon-facebook.png is from http://facebook.com/favicon.ico and distributed under fair use
icon-statusnet.png is from http://status.net/favicon.ico and distributed under fair use

path: public/plugins/ShareNotice/css/README


code:
.notice-share {
    width: 24px;
    float: right;
}

.notice-share li a {
    display: block;
    width: 16px;
    height: 16px;
    background: url(icon-share.png) no-repeat;
}
.notice-share li.notice-share-twitter a {
    background-image: url(icon-twitter.png);
}
.notice-share li.notice-share-facebook a {
    background-image: url(icon-facebook.png);
}
.notice-share li.notice-share-statusnet a {
    background-image: url(icon-statusnet.png);
}
.notice-share li a span {
    display: none;
}


code:
/* undo insane stuff from core styles */
#add-mirror-wizard img {
    display: inline;
}

/* we need #something to override most of the #content crap */

#add-mirror-wizard {
    margin-left: 20px;
    margin-right: 20px;
}

#add-mirror-wizard .provider-list table {
    width: 100%;
}

#add-mirror-wizard .provider-heading img {
    vertical-align: middle;
}
#add-mirror-wizard .provider-heading {
    cursor: pointer;
}
#add-mirror-wizard .provider-detail fieldset {
    margin-top: 8px; /* hack */
    margin-bottom: 8px; /* hack */
}


code:
$(function() {
    /**
     * Append 'ajax=1' parameter onto URL.
     */
    function ajaxize(url) {
        if (url.indexOf('?') == '-1') {
            return url + '?ajax=1';
        } else {
            return url + '&ajax=1';
        }
    }

    var addMirror = $('#add-mirror');
    var wizard = $('#add-mirror-wizard');
    if (wizard.length > 0) {
        var list = wizard.find('.provider-list');
        var providers = list.find('.provider-heading');
        providers.click(function(event) {
            console.log(this);
            var targetUrl = $(this).find('a').attr('href');
            if (targetUrl) {
                // Make sure we don't accidentally follow the direct link
                event.preventDefault();

                var node = this;
                function showNew() {
                    var detail = $('

').insertAfter(node);
                    detail.load(ajaxize(targetUrl), function(responseText, testStatus, xhr) {
                        detail.slideDown('fast', function() {
                            detail.find('input[type="text"]').focus();
                        });
                    });
                }

                var old = addMirror.find('.provider-detail');
                if (old.length) {
                    old.slideUp('fast', function() {
                        old.remove();
                        showNew();
                    });
                } else {
                    showNew();
                }
            }
        });
    }
});


code:
jQuery(function($){
  $('#notice_data-text').bind('keydown',function(e){
    if (e.which==9) {
      setTimeout(function(){  $('#notice_action-submit').focus();  },15);
    }
  });
});


code:
* To use a theme other than neo, add this to config.php:
$config['site']['theme'] = 'yourthemename';

* To use/import the base theme, add this to your theme.ini file:
include=base

* To include an external CSS resource (e.g. for a webfont), add this to the top of your theme.ini file:
external[]="yourexternalURL"

path: public/theme/README