├── srv ├── .gitignore ├── server.js ├── README.rst └── mongo-by-params.js ├── client ├── img │ ├── de.png │ ├── en.png │ ├── fr.png │ ├── nl.png │ ├── cross.png │ └── spinner.gif ├── js │ ├── jquery │ │ ├── jquery.cometd-timestamp.js │ │ ├── jquery.cometd-reload.js │ │ ├── jquery.cookie.js │ │ ├── jquery.cometd.js │ │ ├── json2.js │ │ ├── jquery-ui-1.8.17.custom.min.js │ │ └── jquery-1.7.1.min.js │ ├── cometd │ │ ├── TimeStampExtension.js │ │ └── ReloadExtension.js │ ├── scrollappend.js │ ├── urlparams.js │ ├── util.js │ ├── bayeuxclient.js │ ├── chatbox.js │ ├── mapselect.js │ ├── wikisearch.js │ ├── portalsearch.js │ ├── alchemy.js │ ├── objectview.js │ └── userbox.js ├── README.rst └── index.html ├── go.sh ├── README.rst └── LICENSE /srv/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /client/img/de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KBNLresearch/hack4europe/master/client/img/de.png -------------------------------------------------------------------------------- /client/img/en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KBNLresearch/hack4europe/master/client/img/en.png -------------------------------------------------------------------------------- /client/img/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KBNLresearch/hack4europe/master/client/img/fr.png -------------------------------------------------------------------------------- /client/img/nl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KBNLresearch/hack4europe/master/client/img/nl.png -------------------------------------------------------------------------------- /client/img/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KBNLresearch/hack4europe/master/client/img/cross.png -------------------------------------------------------------------------------- /client/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KBNLresearch/hack4europe/master/client/img/spinner.gif -------------------------------------------------------------------------------- /client/js/jquery/jquery.cometd-timestamp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dual licensed under the Apache License 2.0 and the MIT license. 3 | * $Revision: 736 $ $Date: 2009-08-24 17:35:54 +0200 (Mon, 24 Aug 2009) $ 4 | */ 5 | (function($) 6 | { 7 | $.cometd.registerExtension('timestamp', new org.cometd.TimeStampExtension()); 8 | })(jQuery); -------------------------------------------------------------------------------- /client/js/jquery/jquery.cometd-reload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dual licensed under the Apache License 2.0 and the MIT license. 3 | * $Revision: 686 $ $Date: 2009-07-03 11:07:24 +0200 (Fri, 03 Jul 2009) $ 4 | */ 5 | (function($) 6 | { 7 | // Remap cometd COOKIE functions to jquery cookie functions 8 | // Avoid to set to undefined if the jquery cookie plugin is not present 9 | if ($.cookie) 10 | { 11 | org.cometd.COOKIE.set = $.cookie; 12 | org.cometd.COOKIE.get = $.cookie; 13 | } 14 | 15 | $.cometd.registerExtension('reload', new org.cometd.ReloadExtension()); 16 | })(jQuery); -------------------------------------------------------------------------------- /client/js/cometd/TimeStampExtension.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dual licensed under the Apache License 2.0 and the MIT license. 3 | * $Revision: 705 $ $Date: 2009-07-21 12:31:39 +0200 (Tue, 21 Jul 2009) $ 4 | */ 5 | 6 | if (typeof dojo!="undefined") 7 | { 8 | dojo.provide("org.cometd.TimeStampExtension"); 9 | } 10 | 11 | /** 12 | * The timestamp extension adds the optional timestamp field to all outgoing messages. 13 | */ 14 | 15 | org.cometd.TimeStampExtension = function() 16 | { 17 | this.outgoing = function(message) 18 | { 19 | message.timestamp = new Date().toUTCString(); 20 | return message; 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /client/js/scrollappend.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | (function( $ ) { 16 | /** Append to scrollable div and scroll down **/ 17 | $.fn.scrollAppend = function(innerds, opts) { 18 | return this.each(function() { 19 | $(this).append(innerds, opts); 20 | this.scrollTop = this.scrollHeight; 21 | }); 22 | } 23 | })(jQuery); 24 | -------------------------------------------------------------------------------- /client/js/urlparams.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | // http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript 16 | // Andy E 17 | var urlParams = {}; 18 | (function () { 19 | var e, 20 | a = /\+/g, // Regex for replacing addition symbol with a space 21 | r = /([^&=]+)=?([^&]*)/g, 22 | d = function (s) { return decodeURIComponent(s.replace(a, " ")); }, 23 | q = window.location.search.substring(1); 24 | while (e = r.exec(q)) 25 | urlParams[d(e[1])] = d(e[2]); 26 | })(); 27 | -------------------------------------------------------------------------------- /go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | 17 | sudo apt-get install git-core curl build-essential openssl libssl-dev mongodb 18 | 19 | git clone https://github.com/joyent/node.git 20 | cd node 21 | git checkout v0.6.3 22 | ./configure 23 | make 24 | sudo make install 25 | curl http://npmjs.org/install.sh | sudo sh 26 | cd ../srv 27 | mkdir node_modules 28 | npm install faye mongodb mongojs node-static qs 29 | cd .. 30 | rm -rf node 31 | cd srv 32 | echo "please surf to localhost:8000" 33 | node server.js 34 | -------------------------------------------------------------------------------- /client/js/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | var Util = { 16 | options: {}, 17 | /** Read out override setting **/ 18 | readOpt: function(setting, defaultOpt) { 19 | return Util.options[setting] ? Util.options[setting] : defaultOpt 20 | }, 21 | 22 | timeFormat: function(timeStamp) { 23 | var time = new Date(timeStamp); 24 | var aTime = [ 25 | "" + time.getHours(), 26 | "" + time.getMinutes(), 27 | "" + time.getSeconds() 28 | ]; 29 | $.each(aTime, function(i, x) { 30 | if(x.length == 1) { aTime[i] = "0" + x; } 31 | }); 32 | return aTime[0] + ":" + aTime[1] + ":" + aTime[2]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /srv/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | var http = require('http'); 16 | var url = require('url'); 17 | var faye = require('faye'); 18 | var bayeux = new faye.NodeAdapter({mount: '/feed', timeout: 45}); 19 | var static = require("node-static"); 20 | var fileServer = new static.Server('../client'); 21 | var db = require('mongojs').connect('test'); 22 | var fayeClient = new faye.Client('http://localhost:8000/feed'); 23 | 24 | var httpServer = http.createServer(function (request, response) { 25 | var path = url.parse(request.url, true).pathname; 26 | if(path.match(/^\/db*/)) { 27 | require("./mongo-by-params.js").routeRequest(db, request, response, path, { 28 | callback: function(data) { 29 | fayeClient.publish('/main', {user: "database", msg: data, time: new Date().getTime()}); 30 | } 31 | }); 32 | } else { 33 | request.addListener('end', function () { 34 | fileServer.serve(request, response); 35 | }); 36 | } 37 | }); 38 | 39 | bayeux.attach(httpServer); 40 | httpServer.listen(8000); 41 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | The Portal Thingy Hack4Europe Hackathon entry 2 | ============================================= 3 | 4 | Live Demo 5 | --------- 6 | `Portal Thingy `_. 7 | 8 | Description 9 | ----------- 10 | This portal enables users to search the Europeana collections and to enrich it metadata using a local mongodb and remote API's. 11 | 12 | 13 | Adding the API keys 14 | ------------------- 15 | In order for the portal to actually do anything with the remote API's two API keys need to be entered in the file `client/index.html `_. The Europeana API key goes on `line 23 `_. And the Alchemy API key (which is restricted to non-profit research activity) goes on `line 28 `_. 16 | 17 | 18 | Running out of the box 19 | ---------------------- 20 | On a Ubuntu/Debian distribution with Aptitude the ./go.sh shell script should run out of the box, installing all prerequisites and starting the portal on a local host. Installing the prerequisites can take a long time, seeing as the entire google V8 engine and node.js need to be built from source. Probably it's best to run it as a sudo user. Even better is to have a good look at the script and only install the prerequisites that you do not have installed yet. 21 | 22 | - Starting the portal:: 23 | 24 | $ sudo ./go.sh 25 | 26 | - If everything went well, the portal can be visited locally at your `local host on port 8000 `_. 27 | 28 | More on the Project 29 | ------------------- 30 | The portal uses a mongodb installment to store user's contributions. New records can be added through RESTful local-domain ajax calls, querying on the database can be done cross-domain as well, using JSONP. `More about the database `_. For instructions on how to let client code talk to the db go `here `_ 31 | -------------------------------------------------------------------------------- /client/js/jquery/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dual licensed under the Apache License 2.0 and the MIT license. 3 | * $Revision: 1645 $ $Date: 2011-03-22 00:16:12 +0100 (Tue, 22 Mar 2011) $ 4 | */ 5 | (function($) 6 | { 7 | var _defaultConfig = { 8 | 'max-age' : 30 * 60, 9 | path : '/' 10 | }; 11 | 12 | function _set(key, value, options) 13 | { 14 | var o = $.extend({}, _defaultConfig, options); 15 | if (value === null || value === undefined) 16 | { 17 | value = ''; 18 | o['max-age'] = 0; 19 | o.expires = new Date(new Date().getTime() - 1000); 20 | } 21 | 22 | // Create the cookie string 23 | var result = key + '=' + encodeURIComponent(value); 24 | if (o.expires && o.expires.toUTCString) 25 | { 26 | result += '; expires=' + o.expires.toUTCString(); 27 | } 28 | if (o['max-age'] && typeof o['max-age'] === 'number') 29 | { 30 | result += '; max-age=' + o['max-age']; 31 | } 32 | if (o.path) 33 | { 34 | result += '; path=' + (o.path); 35 | } 36 | if (o.domain) 37 | { 38 | result += '; domain=' + (o.domain); 39 | } 40 | if (o.secure) 41 | { 42 | result +='; secure'; 43 | } 44 | 45 | document.cookie = result; 46 | } 47 | 48 | function _get(key) 49 | { 50 | var cookies = document.cookie.split(';'); 51 | for (var i = 0; i < cookies.length; ++i) 52 | { 53 | var cookie = $.trim(cookies[i]); 54 | if (cookie.substring(0, key.length + 1) == (key + '=')) 55 | { 56 | return decodeURIComponent(cookie.substring(key.length + 1)); 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | $.cookie = function(key, value, options) 63 | { 64 | if (arguments.length > 1) 65 | { 66 | _set(key, value, options); 67 | return undefined; 68 | } 69 | else 70 | { 71 | return _get(key); 72 | } 73 | }; 74 | 75 | })(jQuery); 76 | -------------------------------------------------------------------------------- /client/README.rst: -------------------------------------------------------------------------------- 1 | Client 2 | ====== 3 | 4 | The portal's activities. 5 | 6 | Adding the API keys 7 | ------------------- 8 | In order for the portal to actually do anything with the remote API's two API keys need to be entered in the file `index.html `_. The Europeana API key goes on `line 23 `_. And the Alchemy API key (which is restricted to non-profit research activity) goes on `line 28 `_. 9 | 10 | Storing a record to the database 11 | --------------- 12 | 13 | Easiest is to use the 'upsert' action - I only use that. I wrote handlers for other types of updates, but upserting is fun and easy: if the record defined by your query exists it gets updated, otherwise it gets created. 14 | 15 | Example from the project:: 16 | 17 | var data = { 18 | recordId: "[your record id; is not necessary but makes sense if you want to link to some other data]", 19 | lemma: "Your_Wiki_lemma", 20 | type: entity.type, 21 | text: entity.text 22 | }; 23 | $.ajax({ 24 | type: "POST", 25 | url: "db/named_entities", 26 | data: {upsert: data, set: data}, /** the actual instructions, ('upsert' defines the record to find, 'set' is the actual update) **/ 27 | success: function(data) { 28 | saveButton.attr("disabled", "true"); 29 | saveButton.html("Enrichment saved"); 30 | } 31 | }); 32 | 33 | Another example from the project:: 34 | 35 | var latLon = {lat: 12.34, lon: 56.7}; 36 | $.ajax({ 37 | type: "POST", 38 | url: "db/geolocations", 39 | data: { 40 | upsert: {recordId: recordId, geo: latLon }, 41 | set: {recordId: recordId, geo: latLon } 42 | } 43 | }); 44 | 45 | Querying the db using ajax 46 | ---- 47 | ...is done asynchronously, because stuff gets streamed, so you need the entire block of data to make sure everything is in before another you do another query call that messes up the first call... Believe me, it happens:: 48 | 49 | $.ajax("db/geolocations", { 50 | async: false, 51 | data: {recordId: recordId}, 52 | success: function(data) { 53 | if(data[0] != null) { 54 | $.each(data, function(i, record) { 55 | if(record == null) { return; } 56 | console.log(record); 57 | }); 58 | } 59 | } 60 | }); 61 | 62 | -------------------------------------------------------------------------------- /client/js/bayeuxclient.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | function BayeuxClient(host, port, path, logLevel) { 16 | var url = "http://" + host + ":" + port + "/" + path.replace(/^\//, ""); 17 | var logLevel = logLevel; 18 | var comet = $.cometd; 19 | this.isConnected = false; 20 | var subscriptions = {}; 21 | 22 | this.connect = function(callbacks) { 23 | comet.websocketEnabled = true; 24 | comet.configure({ 25 | url: url, // "http://192.168.0.102:8000/bayeux/", 26 | logLevel: logLevel ? logLevel : 'info' 27 | }); 28 | if(callbacks.onHandshake) 29 | comet.addListener('/meta/handshake', callbacks.onHandshake); 30 | 31 | var _this = this; 32 | comet.addListener('/meta/connect', function(msg) { 33 | if(msg.successful === true) 34 | _this.isConnected = true; 35 | else 36 | _this.isConnected = false; 37 | if(callbacks.onConnect) 38 | callbacks.onConnect(_this.isConnected); 39 | }); 40 | comet.handshake(); 41 | } 42 | 43 | this.disconnect = function() { 44 | for(var sub in subscriptions) { 45 | comet.unsubscribe(subscriptions[sub]); 46 | } 47 | comet.disconnect(); 48 | }, 49 | 50 | this.addChannel = function(channel, listener) { 51 | var channelId = channel.replace(/\//g, "_"); 52 | if(!subscriptions[channelId]) { 53 | var sub = comet.subscribe(channel, listener); 54 | subscriptions[channelId] = sub; 55 | } 56 | return channelId; 57 | } 58 | 59 | this.dropChannel = function(channelId) { 60 | if(subscriptions[channelId]) { 61 | comet.unsubscribe(subscriptions[channelId]); 62 | subscriptions[channelId] = null; 63 | } 64 | } 65 | 66 | this.hasChannel = function(channelPath) { 67 | var channelId = channelPath.replace(/\//g, "_"); 68 | return subscriptions[channelId] != null; 69 | } 70 | 71 | this.publish = function(channelId, data) { 72 | comet.batch(function() { 73 | comet.publish(channelId.replace(/_/g, "/"), data); 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /client/js/chatbox.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | (function( $ ) { 16 | $.fn.chatBox = function(opts) { 17 | Util.options = opts; 18 | var userName = opts["userName"]; 19 | var client = opts["client"]; 20 | var chatLabel = Util.readOpt("chatLabel", "Chatbericht"); 21 | var chatLabelId = Util.readOpt("chatLabelId", "chat_label"); 22 | var chatLabelCss = Util.readOpt("chatLabelCss", { 23 | fontWeight: "bold", 24 | fontSize: "11px", 25 | fontFamily: "sans, arial" 26 | }); 27 | var channelPath = Util.readOpt("channel", "/main"); 28 | var inputId = Util.readOpt("inputId", "chatMessageInput"); 29 | var chatMsgBoxId = Util.readOpt("chatMsgBoxId", "chatMessageBox"); 30 | var chatMsgBoxCss = Util.readOpt("chatMsgBoxCss", { 31 | height: "100px", 32 | overflowY: "auto", 33 | fontSize: "11px", 34 | fontFamily: "arial, sans", 35 | backgroundColor: "#eee", 36 | border: "1px solid" 37 | }); 38 | var channel = null; 39 | var receive = function(message) { 40 | if(message.data && message.data.msg && message.data.user) { 41 | $("#" + chatMsgBoxId).append("(" + Util.timeFormat(message.data.time) + ") "); 42 | $("#" + chatMsgBoxId).append("" + message.data.user + ": "); 43 | $("#" + chatMsgBoxId).scrollAppend(message.data.msg + "
"); 44 | } 45 | }; 46 | if(client && userName) { 47 | if(!client.hasChannel(channelPath)) { 48 | this.html("" + chatLabel + ":  "); 49 | this.append(""); 50 | this.append("
"); 51 | $("#" + chatLabelId).css(chatLabelCss); 52 | $("#" + chatMsgBoxId).css(chatMsgBoxCss); 53 | channel = client.addChannel(channelPath, receive); 54 | $("#" + inputId).keyup(function(e) { 55 | if(e.keyCode == 13 && $(this).val().length > 0) { 56 | client.publish(channel, { 57 | user: userName, 58 | msg: $(this).val().replace(/&/g, "&").replace(//g, ">"), 59 | time: new Date().getTime() 60 | }); 61 | $(this).val(""); 62 | } 63 | }); 64 | } 65 | } else { 66 | this.html("niet verbonden") 67 | } 68 | return this; 69 | }})(jQuery); 70 | -------------------------------------------------------------------------------- /client/js/mapselect.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | (function( $ ) { 16 | $.fn.mapSelect = function(opts) { 17 | Util.options = opts ? opts : {}; 18 | var callback = Util.readOpt("callback", function(ll) { alert(ll.lat + "/" + ll.lon); } ); 19 | var recordId = opts.recordId; 20 | var map = null; 21 | var curMarker = null; 22 | var markers= null; 23 | var hitMarkers = []; 24 | var existingMarkerMap = []; 25 | 26 | markers = new OpenLayers.Layer.Markers("Markers"); 27 | map = new OpenLayers.Map(this.attr("id")); 28 | map.addLayer(new OpenLayers.Layer.OSM()); 29 | var lonLat = new OpenLayers.LonLat(13.411007, 52.521642).transform( 30 | new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984 31 | map.getProjectionObject() // to Spherical Mercator Projection 32 | ); 33 | 34 | map.addLayer(markers); 35 | map.setCenter(lonLat); 36 | map.zoomTo(3); 37 | map.events.register('click', map, function (e) { 38 | var lonLat = map.getLonLatFromPixel(e.xy); 39 | var llOut = new OpenLayers.LonLat(lonLat.lon, lonLat.lat).transform( 40 | map.getProjectionObject(), // from Spherical Mercator Projection 41 | new OpenLayers.Projection("EPSG:4326") // transform to WGS 1984 42 | ); 43 | 44 | var icon = new OpenLayers.Icon('http://mapdroid.googlecode.com/files/marker.png'); 45 | if(!curMarker) { 46 | curMarker = new OpenLayers.Marker(lonLat, icon); 47 | } else { 48 | curMarker.lonlat = lonLat; 49 | markers.removeMarker(curMarker); 50 | } 51 | markers.addMarker(curMarker); 52 | callback({lat: llOut.lat, lon: llOut.lon}); 53 | }); 54 | console.log(recordId); 55 | if(recordId) { 56 | $.ajax("db/geolocations", { 57 | async: false, 58 | data: {recordId: recordId}, 59 | success: function(data) { 60 | $.each(data, function(i, info) { 61 | if(info == null) { return; } 62 | var lonLat = new OpenLayers.LonLat(info.geo.lon, info.geo.lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); 63 | var icon = new OpenLayers.Icon('http://mapdroid.googlecode.com/files/marker.png'); 64 | var marker = new OpenLayers.Marker(lonLat, icon); 65 | 66 | markers.addMarker(marker); 67 | }); 68 | } 69 | }); 70 | } 71 | 72 | }})(jQuery); 73 | -------------------------------------------------------------------------------- /client/js/wikisearch.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | (function( $ ) { 16 | $.fn.wikiSearch = function(opts) { 17 | Util.options = opts; 18 | var labelTxt = Util.readOpt("label", "Search Wikipedia"); 19 | var lang = Util.readOpt("lang", "en"); 20 | var label = $("