How can I refresh the leaflet marker value - ajax

Good evening,
I am using Leaflet.js to localize the station which measure the temperature of bud. The app needs to generate an alarm when the temperature is too low.
The user can view the temperature shown in markers.
The app needs to request a MySQL database to collect the needed records.
On each refreshed, I do not want to reload the map, because the station does not move.
Is there a way to reload only the makers, or to update the value?
Here is how I load my map
function refreshMap(){
loadMap();
}
function loadMap(){
var get_map_center = [];
$.ajax({
type: "POST",
url: "https://sub.domain.ch/sql/mysql.php",
crossDomain: true,
success: result,
error: error,
dataType: "json"
});
function error(data)
{
alert("Error getting datas from DB");
console.log("Error getting datas from DB");
console.log(data);
showMap(46.187164,5.997526,null);
}
function result(data){
console.info("data:",data);
for(var y=0; y < data.map_center.length; y++)
{
get_map_center.push(data.map_center[y]);
}
var allMarkers = [];
var markers = L.markerClusterGroup({
showCoverageOnHover: false
});
// THIS ADD AN IMAGE IF THE TEMPERATURE ARE NORMAL; LIMITE OR TO LOW
var nhtml = '<img src="img/property-types/vineyard.png">';
for (var i = 0; i < data.properties.length; i++)
{
allMarkers.push(L.latLng(data.properties[i]['la'], data.properties[i]['lo']));
if((data.properties[i]['b1']>=data.properties[i]['se'] && data.properties[i]['b1'] < data.properties[i]['se']+1) ||
(data.properties[i]['b2']>=data.properties[i]['se'] && data.properties[i]['b2'] < data.properties[i]['se']+1) ||
(data.properties[i]['b3']>=data.properties[i]['se'] && data.properties[i]['b3'] < data.properties[i]['se']+1) ||
(data.properties[i]['b4']>=data.properties[i]['se'] && data.properties[i]['b4'] < data.properties[i]['se']+1)
)
{
nhtml = '<img src="img/property-types/vineyard-orange.png">';
}
if(((data.properties[i]['b1'] < data.properties[i]['se']) && data.properties[i]['b1'] != null) ||
((data.properties[i]['b2'] < data.properties[i]['se']) && data.properties[i]['b2'] != null) ||
((data.properties[i]['b3'] < data.properties[i]['se']) && data.properties[i]['b3'] != null) ||
((data.properties[i]['b4'] < data.properties[i]['se']) && data.properties[i]['b4'] != null)
)
{
nhtml = '<img src="img/property-types/vineyard-red.png">';
}
else{
nhtml = '<img src="img/property-types/vineyard.png">';
}
var _icon = L.divIcon({
//html: '<img src="' + locations[i][7] +'">',
html: nhtml,
iconSize: [40, 48],
iconAnchor: [20, 48],
popupAnchor: [0, -48]
});
var title = data.properties[i]['station'];
var marker = L.marker(new L.LatLng(data.properties[i]['la'],data.properties[i]['lo']), {
title: title,
icon: _icon
});
var str ='';
if(data.properties[i]['b1'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b1'] + '°C</div>');
}
if(data.properties[i]['b2'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b2'] + '°C</div>');
}
if(data.properties[i]['b3'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b3'] + '°C</div>');
}
if(data.properties[i]['b4'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b4'] + '°C</div>');
}
marker.bindPopup(
'<div class="property">' +
'' +
'<div class="property-image">' +
'<img src="img/stations/station-' + data.properties[i]['id_station'] + '.jpg">' +
'</div>' +
'<div class="overlay">' +
'<div class="info">' +
'<h3>' + data.properties[i]['station'] + '</h3>' +
'<p>' + data.properties[i]['da'] + '</p>' +
// '<figure>' + data.properties[i]['la'] + ' ' + data.properties[i]['lo'] +'</figure>' +
str +
'<p> <a data-field=' + data.properties[i]['id_field'] +'" data-station=' + data.properties[i]['id_station'] +'" href="https://bud.eco-sensors.ch/charts.php?field='+ data.properties[i]['id_field'] +'#st-'+ data.properties[i]['id_station'] +'">Historique</a></p>' +
//'<div class="tag"> ' + data.properties[i]['se'] + '°C</div>' +
'</div>' +
'</div>' +
'' +
'</div>',{autoClose: true, closeOnClick: true, closeButton: true}
);
/*
*. THOSE VALUES NEEED TO BE UPDATED
*/
var val = '';
if(!isEmpty(data.properties[i]['b4']))
{
val = data.properties[i]['b4'] +'°C ';
}
if(!isEmpty(data.properties[i]['b1']))
{
val = val + data.properties[i]['b1'] +'°C ';
}
if(!isEmpty(data.properties[i]['su']))
{
val = val + data.properties[i]['su'] +'W/m2 ';
}
if(!isEmpty(data.properties[i]['an']))
{
val = val + data.properties[i]['an'] +'km/h ';
}
if(!isEmpty(data.properties[i]['sb']))
{
val = val + data.properties[i]['sb'] +'°C (B)';
}
if(!isEmpty(data.properties[i]['sl']))
{
val = val + data.properties[i]['sl'] +'°C (F)';
}
marker.bindTooltip(val, {direction: 'bottom', permanent: true});
markers.addLayer(marker);
}
showMap(get_map_center[0][0],get_map_center[0][1], markers);
} // End result
}
/*
* BUILD THE MAP AFTER THE FUNCTION 'result' OF AJAX
* I need it to make sure that the map is initialized when AJAX finishes loading
*/
function showMap(lat,lng, markers){
var map = L.map('map', {
//center: [46.187164,5.997526],
center: [lat,lng],
zoom: 14,
scrollWheelZoom: false
});
// add an OpenStreetMap tile layer
L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
//subdomains: '0123',
maxZoom: 20,
attribution: 'OpenStreetMap contributors, CC-BY-SA'
}).addTo(map);
if(markers!=null){
map.addLayer(markers);
}
}
Maybe it can done better, but this works fine, except that I need to update the value in the bind tooltips when I make a new MySQL request to get the new value.
I hope I clearly explained my needs ;)
Is possible to reload the markers (or the value) without reloading the full map?
Many thanks

Create your map outside (=global), not in a function
var map = L.map('map', {
//center: [46.187164,5.997526],
center: [0, 0],
zoom: 14,
scrollWheelZoom: false
});
// add an OpenStreetMap tile layer
L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
//subdomains: '0123',
maxZoom: 20,
attribution: 'OpenStreetMap contributors, CC-BY-SA'
}).addTo(map);
function loadMap() {
...
Create a featureGroup where you add the markers instead adding them to the map:
var map = ...
// add an OpenStreetMap tile layer
L.tileLayer( ... ).addTo(map);
var fg = L.featureGroup().addTo(map);
function loadMap() {
...
When loadMap is called, clear the featureGroup and then add the markers to it (then the old markers are removed and the new one are added => refresh Markers)
Instead of showMap:
function result(){
...
marker.bindTooltip(val, {direction: 'bottom', permanent: true});
markers.addLayer(marker);
}
showMap(get_map_center[0][0],get_map_center[0][1], markers);
} // End result
}
us this code:
function result(){
...
marker.bindTooltip(val, {direction: 'bottom', permanent: true});
markers.addLayer(marker);
}
fg.clearLayers();
fg.addLayer(markers);
map.panTo(get_map_center[0][0],get_map_center[0][1]);
} // End result
}
When you don't want that the map center is refreshed you can use a flag:
var map = ...
var fg = ...
var centered = false;
...
function result(){
...
fg.clearLayers();
fg.addLayer(markers);
if(!centered){
centered = true;
// map is centered only once
map.panTo(get_map_center[0][0],get_map_center[0][1]);
}
Summary:
var map = L.map('map', {
//center: [46.187164,5.997526],
center: [0, 0],
zoom: 14,
scrollWheelZoom: false
});
// add an OpenStreetMap tile layer
L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
//subdomains: '0123',
maxZoom: 20,
attribution: 'OpenStreetMap contributors, CC-BY-SA'
}).addTo(map);
var fg = L.featureGroup().addTo(map);
var centered = false;
function refreshMap(){
loadMap();
}
function loadMap(){
var get_map_center = [];
$.ajax({
type: "POST",
url: "https://sub.domain.ch/sql/mysql.php",
crossDomain: true,
success: result,
error: error,
dataType: "json"
});
function error(data)
{
alert("Error getting datas from DB");
console.log("Error getting datas from DB");
console.log(data);
showMap(46.187164,5.997526,null);
}
function result(data){
console.info("data:",data);
for(var y=0; y < data.map_center.length; y++)
{
get_map_center.push(data.map_center[y]);
}
var allMarkers = [];
var markers = L.markerClusterGroup({
showCoverageOnHover: false
});
// THIS ADD AN IMAGE IF THE TEMPERATURE ARE NORMAL; LIMITE OR TO LOW
var nhtml = '<img src="img/property-types/vineyard.png">';
for (var i = 0; i < data.properties.length; i++)
{
allMarkers.push(L.latLng(data.properties[i]['la'], data.properties[i]['lo']));
if((data.properties[i]['b1']>=data.properties[i]['se'] && data.properties[i]['b1'] < data.properties[i]['se']+1) ||
(data.properties[i]['b2']>=data.properties[i]['se'] && data.properties[i]['b2'] < data.properties[i]['se']+1) ||
(data.properties[i]['b3']>=data.properties[i]['se'] && data.properties[i]['b3'] < data.properties[i]['se']+1) ||
(data.properties[i]['b4']>=data.properties[i]['se'] && data.properties[i]['b4'] < data.properties[i]['se']+1)
)
{
nhtml = '<img src="img/property-types/vineyard-orange.png">';
}
if(((data.properties[i]['b1'] < data.properties[i]['se']) && data.properties[i]['b1'] != null) ||
((data.properties[i]['b2'] < data.properties[i]['se']) && data.properties[i]['b2'] != null) ||
((data.properties[i]['b3'] < data.properties[i]['se']) && data.properties[i]['b3'] != null) ||
((data.properties[i]['b4'] < data.properties[i]['se']) && data.properties[i]['b4'] != null)
)
{
nhtml = '<img src="img/property-types/vineyard-red.png">';
}
else{
nhtml = '<img src="img/property-types/vineyard.png">';
}
var _icon = L.divIcon({
//html: '<img src="' + locations[i][7] +'">',
html: nhtml,
iconSize: [40, 48],
iconAnchor: [20, 48],
popupAnchor: [0, -48]
});
var title = data.properties[i]['station'];
var marker = L.marker(new L.LatLng(data.properties[i]['la'],data.properties[i]['lo']), {
title: title,
icon: _icon
});
var str ='';
if(data.properties[i]['b1'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b1'] + '°C</div>');
}
if(data.properties[i]['b2'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b2'] + '°C</div>');
}
if(data.properties[i]['b3'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b3'] + '°C</div>');
}
if(data.properties[i]['b4'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b4'] + '°C</div>');
}
marker.bindPopup(
'<div class="property">' +
'' +
'<div class="property-image">' +
'<img src="img/stations/station-' + data.properties[i]['id_station'] + '.jpg">' +
'</div>' +
'<div class="overlay">' +
'<div class="info">' +
'<h3>' + data.properties[i]['station'] + '</h3>' +
'<p>' + data.properties[i]['da'] + '</p>' +
// '<figure>' + data.properties[i]['la'] + ' ' + data.properties[i]['lo'] +'</figure>' +
str +
'<p> <a data-field=' + data.properties[i]['id_field'] +'" data-station=' + data.properties[i]['id_station'] +'" href="https://bud.eco-sensors.ch/charts.php?field='+ data.properties[i]['id_field'] +'#st-'+ data.properties[i]['id_station'] +'">Historique</a></p>' +
//'<div class="tag"> ' + data.properties[i]['se'] + '°C</div>' +
'</div>' +
'</div>' +
'' +
'</div>',{autoClose: true, closeOnClick: true, closeButton: true}
);
/*
*. THOSE VALUES NEEED TO BE UPDATED
*/
var val = '';
if(!isEmpty(data.properties[i]['b4']))
{
val = data.properties[i]['b4'] +'°C ';
}
if(!isEmpty(data.properties[i]['b1']))
{
val = val + data.properties[i]['b1'] +'°C ';
}
if(!isEmpty(data.properties[i]['su']))
{
val = val + data.properties[i]['su'] +'W/m2 ';
}
if(!isEmpty(data.properties[i]['an']))
{
val = val + data.properties[i]['an'] +'km/h ';
}
if(!isEmpty(data.properties[i]['sb']))
{
val = val + data.properties[i]['sb'] +'°C (B)';
}
if(!isEmpty(data.properties[i]['sl']))
{
val = val + data.properties[i]['sl'] +'°C (F)';
}
marker.bindTooltip(val, {direction: 'bottom', permanent: true});
markers.addLayer(marker);
}
fg.clearLayers();
fg.addLayer(markers);
if(!centered){
centered = true;
// map is centered only once
map.panTo(get_map_center[0][0],get_map_center[0][1]);
}
} // End result
}
Now you can call loadMap how often you want

So many thank, that works fine. That's great.
I just add to correct this
map.panTo(get_map_center[0][0],get_map_center[0][1]);
to
map.panTo([get_map_center[0][0],get_map_center[0][1]]);
Finally, the map was not show completely
I had that issue when I worked with leaflet, .... some year ago, and I found in my old code the following, and I added it after panto()
map.panTo([get_map_center[0][0] , get_map_center[0][1]]);
map.invalidateSize();
I did not know, if it would solve the problem. But I tried and the map is now well (and fully) displayed
I look at the doc
map.invalidateSize()
Checks if the map container size changed and
updates the map if so — call it after you've changed the map size
dynamically, also animating pan by default. If options.pan is false,
panning will not occur. If options.debounceMoveend is true, it will
delay moveend event so that it doesn't happen often even if the method
is called many times in a row.
and it seems to be right choose, isn't?
So many thanks, that helped a lot!!!

Related

Getting a 500 Internal Server Error Jquery

While everything is running in the software, I get this error when I make a selection from the dropdown list in only one part. Where am I making a mistake? or is it a server error?
I have not received this error in any Laravel before. When trying to get something from a dropdown list, this error comes to the console and there is no reaction on the site.
https://prnt.sc/vaujzf
<script type="text/javascript">
$("ul#product").siblings('a').attr('aria-expanded','true');
$("ul#product").addClass("show");
$("ul#product #adjustment-create-menu").addClass("active");
var lims_product_array = [];
var product_code = [];
var product_name = [];
var product_qty = [];
$('.selectpicker').selectpicker({
style: 'btn-link',
});
$('#lims_productcodeSearch').on('input', function() {
var warehouse_id = $('#warehouse_id').val();
temp_data = $('#lims_productcodeSearch').val();
if (!warehouse_id) {
$('#lims_productcodeSearch').val(temp_data.substring(0, temp_data.length - 1));
alert('Please select Warehouse!');
}
});
$('select[name="warehouse_id"]').on('change', function() {
var id = $(this).val();
$.get('getproduct/' + id, function(data) {
lims_product_array = [];
product_code = data[0];
product_name = data[1];
product_qty = data[2];
$.each(product_code, function(index) {
lims_product_array.push(product_code[index] + ' (' + product_name[index] + ')');
});
});
});
var lims_productcodeSearch = $('#lims_productcodeSearch');
lims_productcodeSearch.autocomplete({
source: function(request, response) {
var matcher = new RegExp(".?" + $.ui.autocomplete.escapeRegex(request.term), "i");
response($.grep(lims_product_array, function(item) {
return matcher.test(item);
}));
},
response: function(event, ui) {
if (ui.content.length == 1) {
var data = ui.content[0].value;
$(this).autocomplete( "close" );
productSearch(data);
};
},
select: function(event, ui) {
var data = ui.item.value;
productSearch(data);
}
});
$("#myTable").on('input', '.qty', function() {
rowindex = $(this).closest('tr').index();
checkQuantity($(this).val(), true);
});
$("table.order-list tbody").on("click", ".ibtnDel", function(event) {
rowindex = $(this).closest('tr').index();
$(this).closest("tr").remove();
calculateTotal();
});
$(window).keydown(function(e) {
if (e.which == 13) {
var $targ = $(e.target);
if (!$targ.is("textarea") && !$targ.is(":button,:submit")) {
var focusNext = false;
$(this).find(":input:visible:not([disabled],[readonly]), a").each(function() {
if (this === e.target) {
focusNext = true;
}
else if (focusNext) {
$(this).focus();
return false;
}
});
return false;
}
}
});
$('#adjustment-form').on('submit', function(e) {
var rownumber = $('table.order-list tbody tr:last').index();
if (rownumber < 0) {
alert("Please insert product to order table!")
e.preventDefault();
}
});
function productSearch(data) {
$.ajax({
type: 'GET',
url: 'lims_product_search',
data: {
data: data
},
success: function(data) {
var flag = 1;
$(".product-code").each(function(i) {
if ($(this).val() == data[1]) {
rowindex = i;
var qty = parseFloat($('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ') .qty').val()) + 1;
$('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ') .qty').val(qty);
checkQuantity(qty);
flag = 0;
}
});
$("input[name='product_code_name']").val('');
if(flag) {
var newRow = $("<tr>");
var cols = '';
cols += '<td>' + data[0] + '</td>';
cols += '<td>' + data[1] + '</td>';
cols += '<td><input type="number" class="form-control qty" name="qty[]" value="1" required step="any" /></td>';
cols += '<td class="action"><select name="action[]" class="form-control act-val"><option value="-">{{trans("file.Subtraction")}}</option><option value="+">{{trans("file.Addition")}}</option></select></td>';
cols += '<td><button type="button" class="ibtnDel btn btn-md btn-danger">{{trans("file.delete")}}</button></td>';
cols += '<input type="hidden" class="product-code" name="product_code[]" value="' + data[1] + '"/>';
cols += '<input type="hidden" class="product-id" name="product_id[]" value="' + data[2] + '"/>';
newRow.append(cols);
$("table.order-list tbody").append(newRow);
rowindex = newRow.index();
calculateTotal();
}
}
});
}
function checkQuantity(qty) {
var row_product_code = $('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ')').find('td:nth-child(2)').text();
var action = $('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ')').find('.act-val').val();
var pos = product_code.indexOf(row_product_code);
if ( (qty > parseFloat(product_qty[pos])) && (action == '-') ) {
alert('Quantity exceeds stock quantity!');
var row_qty = $('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ')').find('.qty').val();
row_qty = row_qty.substring(0, row_qty.length - 1);
$('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ')').find('.qty').val(row_qty);
}
else {
$('table.order-list tbody tr:nth-child(' + (rowindex + 1) + ')').find('.qty').val(qty);
}
calculateTotal();
}
function calculateTotal() {
var total_qty = 0;
$(".qty").each(function() {
if ($(this).val() == '') {
total_qty += 0;
} else {
total_qty += parseFloat($(this).val());
}
});
$("#total-qty").text(total_qty);
$('input[name="total_qty"]').val(total_qty);
$('input[name="item"]').val($('table.order-list tbody tr:last').index() + 1);
}
</script>

Not real random function in a Blogger widget, it always shows 'neighbor' posts from the past

My blog is 12 years old, I have more than 5000 posts. I am using a widget that shows random posts from a specific label. I set it to show 2 posts in the sidebar, and I noticed that these posts are always 'neighbors', which means they are always from the same month in the past. For example, it's always 2 posts from May 2014, or June 2018. It's never something like: 1 post from May 2014 and the other from June 2018. Do you have any idea what the problem is?
Here is the part of the code which (I believe) contains the mistake:
rand=Math.floor((Math.random()*_vRiO.total_entry)+1);
if(rand+bcd140526_post_count>_vRiO.total_entry){
rand=_vRiO.total_entry-bcd140526_post_count+1;
}
if(rand<1){
rand=1;
}
var _vXsM=HOST+_s7IgU[159];
if(bcd140526_index_label){
_vXsM+=_s7IgU[160]+encodeURIComponent(bcd140526_index_label);
}
_vXsM+=_s7IgU[161]+bcd140526_post_count+_s7IgU[162]+rand+_s7IgU[163];
_fIoT(_vXsM);
}else{
_fYbP(json);
}
}
var _vXsM=HOST+_s7IgU[164];
if(bcd140526_index_label){
_vXsM+=_s7IgU[165]+encodeURIComponent(bcd140526_index_label);
}
_vXsM+=_s7IgU[166];
if(bcd140526_sort_by==_s7IgU[167]){
_vXsM+=_s7IgU[168];
}else{
_vXsM+=_s7IgU[169]+bcd140526_post_count;
}
_vXsM+=_s7IgU[170];_fIoT(_vXsM);
I can't paste the whole code, the website doesn't let me. But you can get it here: https://sneeit.com/blogger-random-recent-specific-label-posts-widget-all-in-one-post-feed-widget/
My settings:
Post Count - 2
Post Order - Random
Specific Label - Summer
Show Thumbnail - Checked
Thumbnail Size - 200
Show Label - No
Show Comment Numbers - No
Show Date - No
Show Author Name - No
Show Readmore - No
Show Snippet - No
Show Copyright - No
Design Style - List
I have painstakingly deobfuscated this extension to be able to check how you could modify it (which should be much easier for you if you still want to), and I see that getting "non-neighbor" random numbers is not what this system is designed to do. choosePost(json) chooses one post by number to be the starting post, and makeWidget (which, bizarrely, uses string concatenation and document.write to generate the widget) just uses the first post_count posts after the chosen post, so your objective is not (easily) doable.
var show_thumbnail = true;
var show_label = false;
var show_comment_numbers = false;
var show_date = false;
var show_author_name = false;
var show_readmore = false;
var show_snippet = false;
var hide_copyright = true;
var snippet_length = 150;
var post_count = 3;
var thumbnail_size = 140; // v1.5, only effect with list style
var sort_by = 'random'; // latest or random
var index_label = 'summer';
var design_style = 'list'; // list or column
var date_format = 'mm/dd/yyyy';
var lang_readmore = 'Readmore';
var HOST = '';
function sourceJSfile(url) {
document.write('<script type="text/javascript" src="' + url + '"<\/script>');
}
function generateDate(pub_date, format) {
pub_date = pub_date.split('-');
date = new Date(pub_date[0], pub_date[1] - 1, pub_date[2].substring(0, 2));
dd = date.getDate();
mm = date.getMonth() + 1;
yyyy = date.getFullYear();
format = format.replace('dd', dd);
format = format.replace('mm', mm);
format = format.replace('yyyy', yyyy);
return format;
}
function cleanContent(content) {
var tgt = '';
var imgtag = '<img ';
var srctag = 'src="';
var quote = '\"';
index0 = content.indexOf(imgtag);
if (index0 != -1) {
index1 = content.indexOf(srctag, index0);
index2 = content.indexOf(quote, index1 + srctag.length);
tgt = content.substring(index1 + srctag.length, index2);
}
if (tgt == '') {
imgtag = 'data-thumbnail-src="';
srctag = '"';
index0 = content.indexOf(imgtag);
if (index0 != -1) {
index1 = content.indexOf(srctag, index0 + imgtag.length);
if (index0 != -1) {
tgt = content.substring(index0 + imgtag.length, index1);
}
}
}
if (tgt == '') {
imgtag = '<iframe ';
srctag = 'src="';
quote = '"';
index0 = content.indexOf(imgtag);
if (index0 != -1) {
index1 = content.indexOf(srctag, index0);
if (index0 != -1) {
index2 = content.indexOf(quote, index1 + srctag.length);
if (index0 != -1) {
tgt = content.substring(index1 + srctag.length, index2);
tgt = tgt.replace("http://www.youtube.com/watch?v=", '');
tgt = tgt.replace("http://www.youtube.com/embed/", '');
tgt = tgt.replace('?rel=0', '');
tgt = 'http://img.youtube.com/vi/' + tgt + '/mqdefault.jpg';
}
}
}
}
return tgt;
}
function jsonProcessor(json) {
var data = new Object();
var regex = /<\S[^>]*>/g;
data.id = json.feed.id.$t;
key = 'blog-';
index = data.id.indexOf(key);
data.id = data.id.substring(index + key.length);
data.id = data.id.replace('.comments', '');
data.cate = new Array();
if ('category' in json.feed) {
for (let i = 0; i < json.feed.category.length; i++) {
data.cate[i] = json.feed.category[i].term;
}
}
data.title = '';
if ('title' in json.feed) {
data.title = json.feed.title.$t;
}
data.subtitle = '';
if ('subtitle' in json.feed) {
data.subtitle = json.feed.subtitle.$t;
}
data.admin = new Object();
data.admin.name = 'Anonymous';
data.admin.uri = '';
data.admin.avatar = 'http://img1.blogblog.com/img/anon36.png';
if ('name' in json.feed.author[0]) {
data.admin.name = json.feed.author[0].name.$t;
}
if ('uri' in json.feed.author[0]) {
data.admin.uri = json.feed.author[0].uri.$t;
}
if ('gd$image' in json.feed.author[0]) {
if (json.feed.author[0].gd$image.src != 'http://img1.blogblog.com/img/blank.gif') {
data.admin.avatar = json.feed.author[0].gd$image.src;
}
}
data.total_entry = Number(json.feed.openSearch$totalResults.$t);
data.start_index = Number(json.feed.openSearch$startIndex.$t);
data.item_per_page = Number(json.feed.openSearch$itemsPerPage.$t);
data.entry_number = 0;
if ('entry' in json.feed) {
data.entry_number = json.feed.entry.length;
}
data.entry = new Array();
for (let i = 0; i < data.entry_number; i++) {
data.entry[i] = new Object();
temp = new Object();
entry = json.feed.entry[i];
temp.id = entry.id.$t;
key = 'post-';
index = temp.id.indexOf(key);
temp.id = temp.id.substring(index + key.length);
temp.published = '';
if ('published' in entry) {
temp.published = entry.published.$t;
}
temp.cate = new Array();
if ('category' in entry) {
for (j = 0; j < entry.category.length; j++) {
temp.cate[j] = entry.category[j].term;
}
}
temp.title = '';
if ('title' in entry) {
temp.title = entry.title.$t;
}
temp.content = '';
if ('content' in entry) {
temp.content = entry.content.$t;
}
temp.summary = '';
if ('summary' in entry) {
temp.summary = entry.summary.$t;
}
if (temp.summary == '') {
temp.summary = temp.content.replace(regex, '');
}
if (temp.content == '') {
temp.content = temp.summary;
}
temp.link = '';
temp.reply_label = 'comments';
if ('link' in entry) {
for (j = 0; j < entry.link.length; j++) {
if (entry.link[j].rel == 'alternate') {
temp.link = entry.link[j].href;
}
if (entry.link[j].rel == 'replies') {
temp.reply_label = entry.link[j].title;
}
}
}
temp.author = new Object();
temp.author.name = 'Anonymous';
temp.author.uri = '';
temp.author.avatar = 'http://img1.blogblog.com/img/anon36.png';
a0 = entry.author[0];
if ('name' in a0) {
temp.author.name = a0.name.$t;
}
if ('uri' in a0) {
temp.author.uri = a0.uri.$t;
}
if ('gd$image' in a0) {
if (a0.gd$image.src != 'http://img1.blogblog.com/blank.gif') {
temp.author.avatar = a0.gd$image.src;
}
}
temp.thumbnail = '';
if ('media$thumbnail' in entry) {
temp.thumbnail = entry.media$thumbnail.url;
}
temp.reply_number = 0;
if ('thr$total' in entry) {
temp.reply_number = Number(entry.thr$total.$t);
}
temp.reply_label = temp.reply_label.replace(temp.reply_number + ' ', '');
temp.reply_to = '';
temp.reply_json = '';
temp.reply_title = '';
if ('thr$in-reply-to' in entry) {
temp.reply_to = entry['thr$in-reply-to'].href;
temp.reply_json = entry['thr$in-reply-to'].source;
temp.reply_json = temp.reply_json.replace('/default/', '/summary/');
temp.reply_json = temp.reply_json + '?alt=json-in-script';
}
temp.pid = '';
if ('gd$extendedProperty' in entry) {
for (j = 0; j < entry.gd$extendedProperty.length; j++) {
if (entry.gd$extendedProperty[j].name == 'blogger.itemClass') {
temp.pid = entry.gd$extendedProperty[j].value;
}
}
}
temp.pid = temp.pid.replace('pid-', '');
data.entry[i] = temp;
}
return data;
}
if (typeof(jquery_included) == 'undefined') {
jquery_included = false;
}
function jqueryLoader() {
if (typeof(jQuery) == 'undefined') {
if (!jquery_included) {
jquery_included = true;
var scriptEl = document.createElement('script');
scriptEl.setAttribute('src', 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js');
scriptEl.setAttribute('type', 'text/javascript');
document.getElementsByTagName('head')[0].appendChild(scriptEl);
}
setTimeout(jqueryLoader, 50);
} else {
if (!($('link[href*="font-awesome.css"]').length)) {
linkEl = document.createElement('link');
linkEl.setAttribute('href', 'http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
linkEl.setAttribute('rel', 'stylesheet');
document.head.appendChild(linkEl);
}
}
}
jqueryLoader();
function makeWidget(json) {
var div = '<div style="clear:both!important;float:none;!important;line-height:0!important"></div>';
var jsonOut = jsonProcessor(json);
var docAppend = '';
if (jsonOut.total_entry) {
docAppend += ('<div class="post_feed ' + design_style + ' ' + ((show_thumbnail) ? 'thumb' : 'no-thumb') + '"><ul>');
for (let i = 0; i < jsonOut.total_entry && i < post_count; i++) {
p = jsonOut.entry[i];
docAppend += ('<li class="item item-' + i + '">');
if (!p.thumbnail) {
p.thumbnail = cleanContent(p.content);
}
if (show_thumbnail && p.thumbnail) {
var tgt = p.thumbnail;
if (tgt.indexOf('/s72-c/') != -1){
if (design_style === 'column')
tgt = tgt.replace('/s72-c/', '/s1600/');
else
tgt = tgt.replace('/s72-c/', '/s' + thumbnail_size + '-c/');
} else if (tgt.indexOf('youtube.com') != -1 && tgt.indexOf('/default.') != -1) {
tgt = tgt.replace('/default.', '/mqdefault.');
}
p.thumbnail = tgt;
docAppend += ('<a class="thumbnail" style="width:' + thumbnail_size + 'px;height:' + thumbnail_size + 'px;" href="' + p.link + '"><img src="' + p.thumbnail + '"/></a>');
}
docAppend += '<div class="item-body">';
if (show_label && (typeof(p.cate[0]) != 'undefined')) {
docAppend += ('<a class="cate" href="' + HOST + '/search/label/' + p.cate[0] + '">' + p.cate[0] + '</a>');
}
docAppend += ('<h3 class="title">' + p.title + '</h3>');
if (show_author_name || show_comment_numbers || show_date) {
docAppend += '<div class="meta">';
if (show_author_name) {
docAppend += ('<span class="meta-item author-name"><i class="fa fa-user"></i> ' + p.author.name + '</span>');
}
if (show_comment_numbers) {
docAppend += ('<span class="meta-item comment-number"><i class="fa fa-comment"></i> ' + p.reply_number + '</span>');
}
if (show_comment_numbers) {
docAppend += ('<span class="meta-item date-time"><i class="fa fa-clock-o"></i> ' + generateDate(p.published, date_format) +'</span>');
}
docAppend += (div + '</div>' + div);
}
if (show_snippet) {
if (p.summary.length > snippet_length) {
p.summary = p.summary.substring(0, snippet_length) + '...';
}
if (show_readmore) {
p.summary += ' ' + lang_readmore + '';
}
docAppend += ('<p class="snippet">' + p.summary + '</p>');
}
docAppend += (div + '</div>' + div);
docAppend += ('</li>');
}
docAppend += ('</ul>');
if (!hide_copyright) {
docAppend += div;
docAppend += '<a target="_blank" class="copyright" href="http://www.sneeit.com/2014/05/blogger-random-recent-specific-label-posts-widget-all-in-one-post-feed-widget" style="font-size: 11px!important;text-align:right;visibility: visible;!important;text-indent:0!important;height:auto!important;width:100%!important;position:static!important;color:#999!important;display:block!important;opacity:1!important;">BloggerWidget</a>';
}
docAppend += ('</div>' + div);
} else {
docAppend += '<p><em>Have no posts</em><p>';
}
document.write(docAppend);
}
function choosePost(json) {
if (sort_by == 'random') {
var processedJSON = jsonProcessor(json);
rand = Math.floor((Math.random() * processedJSON.total_entry) + 1);
if (rand + post_count > processedJSON.total_entry) {
rand = processedJSON.total_entry - post_count + 1;
}
if (rand < 1) {
rand = 1;
}
var request = HOST + '/feeds/posts/default';
if (index_label) {
request += '/-/' + encodeURIComponent(index_label);
}
request += '?alt=json-in-script&max-result=' + post_count + '&start-index=' + rand + '&callback=makeWidget';
sourceJSfile(request);
} else {
makeWidget(json);
}
}
var request = HOST + '/feeds/posts/default';
if (index_label) {
request += '/-/' + encodeURIComponent(index_label);
}
request += '?alt=json-in-script';
if (sort_by == 'random') {
request += '&max-results=0';
} else {
request += '&max-results=' + post_count;
}
request += '&callback=choosePost';
sourceJSfile(request);
The modifications will take some work, but the deobfuscated version should be much easier to use. I'd recommend removing jqueryLoader, and to get you started: the API requests are sourceJSfile('/feeds/post/default/-/summer?alt=json-in-script&max-results=1&callback=choosePost'). You'd probably be better off rewriting the thing from scratch than trying to bodge it on top of this code, I think.
PS: This code loads the entire jquery library so it can load some random stylesheet in jqueryLoad.

How do I return the XPath of a tag using XUL?

I would like to select the XPath of a tag and the content of the tag, something similar to what Evernote is doing. However, I cannot find any examples. How could this be achieved?
After some research we found this:
function createXPathFromElement(elm) {
var allNodes = document.getElementsByTagName('*');
for (segs = []; elm && elm.nodeType == 1; elm = elm.parentNode)
{
if (elm.hasAttribute('id')) {
var uniqueIdCount = 0;
for (var n=0;n < allNodes.length;n++) {
if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++;
if (uniqueIdCount > 1) break;
};
if ( uniqueIdCount == 1) {
segs.unshift('id("' + elm.getAttribute('id') + '")');
return segs.join('/');
} else {
segs.unshift(elm.localName.toLowerCase() + '[#id="' + elm.getAttribute('id') + '"]');
}
} else if (elm.hasAttribute('class')) {
segs.unshift(elm.localName.toLowerCase() + '[#class="' + elm.getAttribute('class') + '"]');
} else {
for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) {
if (sib.localName == elm.localName) i++;
};
segs.unshift(elm.localName.toLowerCase() + '[' + i + ']');
};
};
return segs.length ? '/' + segs.join('/') : null;
}
function lookupElementByXPath(path) {
var evaluator = new XPathEvaluator();
var result = evaluator.evaluate(path, document.documentElement, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null);
return result.singleNodeValue;
}

Scroll Events in TouchGridPanel

I am building a mobile application using Sencha Touch 1.0. I need to display report, for that am using grid given by Ext.ux.TouchGridPanel.
It is working fine.
Where as I need to capture Scroll event in Ext.ux.TouchGridPanel.
I have added 'scroll' in bubble event of Dataview.
I am also trying to capture the event after the Dataview created.
But nothing seems to be working. Below is the code which I have changed.
Does anybody has any idea how to capture the start of scroll event?
Thanks in advance.
Ext.ux.TouchGridPanel = Ext.extend(Ext.Panel, {
layout: "fit",
multiSelect: false,
initComponent: function () {
var me = this;
me.items = me.dataview = me.buildDataView();
Ext.ux.TouchGridPanel.superclass.initComponent.call(me);
var store = me.store;
store.on("update", me.dispatchDataChanged, me);
var dataview = me.dataview;
dataview.on('scroll', me.startScroll);
},
dispatchDataChanged: function (store, rec, operation) {
var me = this;
me.fireEvent("storeupdate", store, rec, operation);
},
startScroll: function (scroller, offset) {
console.log('is this event captured???')
var me = this;
me.fireEvent("scroll", this.scroller, offset);
},
buildDataView: function () {
var me = this, colModel = me.colModel, colNum = me.getColNum(false), cellWidth = 100 / colNum,
colTpl = '<div class="x-grid-head">';
colTpl += '<thead><tr class="x-grid-header">';
for (var i = 0; i < colModel.length; i++) {
var col = colModel[i];
var width = (Ext.isDefined(col.width)) ? ("width =" + (col.width - 4) + "%") : '';
colTpl += '<th class="x-grid-cell" ' + width + ' style="' + col.style + '" >' + col.header + '</th>';
}
colTpl += '</tr></thead>';
colTpl += '<tbody ><tpl for="."><tr class="x-grid-row">';
for (var i = 0; i < colModel.length; i++) {
var col = colModel[i];
var width = (Ext.isDefined(col.width)) ? ("width =" + col.width + "%") : '';
colTpl += '<td class="x-grid-cell" style="' + col.style + '" >{' + col.mapping + '}</td>';
}
colTpl += '</tr></tpl></tbody>';
colTpl += '</table></div>'
return new Ext.DataView({
store: me.store,
itemSelector: "tr.x-grid-row",
simpleSelect: me.multiSelect,
scroll: me.scroll,
tpl: new Ext.XTemplate(colTpl,
{
isRowDirty: function (dirty, data) {
return dirty ? "x-grid-row-dirty" : "";
}
}
),
prepareData: function (data, index, record) {
var column,
i = 0,
ln = colModel.length;
var prepare_data = {};
prepare_data.dirtyFields = {};
for (; i < ln; i++) {
column = colModel[i];
if (typeof column.renderer === "function") {
prepare_data[column.mapping] = column.renderer.apply(me, [data[column.mapping], column, record, index]);
} else {
prepare_data[column.mapping] = data[column.mapping];
}
}
prepare_data.isDirty = record.dirty;
prepare_data.rowIndex = index;
return prepare_data;
},
bubbleEvents: [
"beforeselect",
"containertap",
"itemdoubletap",
"itemswipe",
"itemtap",
"selectionchange",
"scroll"
]
});
},
// #private
onScrollStart: function () {
console.log("Are you coming here");
var offset = this.scroller.getOffset();
this.closest = this.getClosestGroups(offset);
this.setActiveGroup(this.closest.current);
},
// #private
onScroll: function (scroller, pos, options) {
}
});
Ext.reg("touchgridpanel", Ext.ux.TouchGridPanel);
We can directly access dataview scroller and check event of the same.
For eg.
newGrid = new Ext.ux.TouchGridPanel({....
after creation of the Panel just access its dataview scroller
newGrid.dataview.scroller.on('scroll', scrollGrid1);
var scrollGrid1 = function(scroller, offsets){
console.log(' Grid scrolling with offset ' + offsets.x + ' & ' + offsets.y);
}

Twitter and jQuery , render tweeted links

I am using jquery ajax to pull from the twitter api, i'm sure there's a easy way, but I can't find it on how to get the "tweet" to render any links that were tweeted to appear as a link. Right now it's only text.
$.ajax({
type : 'GET',
dataType : 'jsonp',
url : 'http://search.twitter.com/search.json?q=nettuts&rpp=2',
success : function(tweets) {
var twitter = $.map(tweets.results, function(obj, index) {
return {
username : obj.from_user,
tweet : obj.text,
imgSource : obj.profile_image_url,
geo : obj.geo
};
});
UPDATE:
The following function (plugin) works perfectly.
(function($) {
$.socialFader = function(options) {
var settings = {
tweetHolder : null,
tweetCount : 100,
fadeSpeed : 500,
tweetName: 'jquery'
};
if (options) {
$.extend(settings, options);
};
var URL = "http://search.twitter.com/search.json?q="+settings.tweetName+"&rpp=" + settings.tweetCount + "&callback=?";
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
var r = '';
if (delta < 60) {
r = 'a minute ago';
} else if(delta < 120) {
r = 'couple of minutes ago';
} else if(delta < (45*60)) {
r = (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (90*60)) {
r = 'an hour ago';
} else if(delta < (24*60*60)) {
r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
r = '1 day ago';
} else {
r = (parseInt(delta / 86400)).toString() + ' days ago';
}
return r;
};
String.prototype.hashify = function() {
return this.replace(/#([A-Za-z0-9\/\.]*)/g, function(m) {
return '<a target="_new" href="http://twitter.com/search?q=' + m.replace('#','') + '">' + m + "</a>";
});
};
String.prototype.linkify = function(){
return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
return m.link(m);
});
};
String.prototype.atify = function() {
return this.replace(/#[\w]+/g, function(m) {
return '' + m + "";
});
};
$.getJSON(URL, function(JSON) {
$.each(JSON.results, function(i, tweet) {
var profilePicture = tweet.profile_image_url;
var userLink = tweet.from_user;
var text = tweet.text;
text = text.linkify().atify().hashify();
var createdAt = new Date(tweet.created_at);
var myTweet = '' + userLink + ' ';
myTweet += text;
$(settings.tweetHolder).append('<li class="cycles">' + myTweet + '</li>');
});
var elements = $(settings.tweetHolder).children();
var timeOutStart = 5000;
function fader(elementId) {
setTimeout(function() {
$(elements[elementId]).fadeOut(settings.fadeSpeed, function() {
$(elements[elementId + 1]).fadeIn(settings.fadeSpeed);
});
}, timeOutStart * (elementId));
};
for (var j = 0; j < elements.length; j++) {
fader(j);
};
});
};
})(jQuery);
Within my Ready Statement :
$.socialFader({ tweetHolder:"#twitter", tweetName:"nettuts", tweetCount:2 });
Here is a plugin I wrote which really simplifies the tweet/json aggregation then parsing. It fades the tweets in and out. Just grab the needed code. Enjoy.
(function($) {
$.socialFader = function(options) {
var settings = {
tweetHolder : null,
tweetCount : 99,
fadeSpeed : 500,
};
if (options) {
$.extend(settings, options);
};
var URL = "http://search.twitter.com/search.json?q=jquery&rpp=" + settings.tweetCount + "&callback=?";
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
var r = '';
if (delta < 60) {
r = 'a minute ago';
} else if(delta < 120) {
r = 'couple of minutes ago';
} else if(delta < (45*60)) {
r = (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (90*60)) {
r = 'an hour ago';
} else if(delta < (24*60*60)) {
r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
r = '1 day ago';
} else {
r = (parseInt(delta / 86400)).toString() + ' days ago';
}
return r;
};
String.prototype.hashify = function() {
return this.replace(/#([A-Za-z0-9\/\.]*)/g, function(m) {
return '<a target="_new" href="http://twitter.com/search?q=' + m.replace('#','') + '">' + m + "</a>";
});
};
String.prototype.linkify = function(){
return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
return m.link(m);
});
};
String.prototype.atify = function() {
return this.replace(/#[\w]+/g, function(m) {
return '' + m + "";
});
};
$.getJSON(URL, function(JSON) {
$.each(JSON.results, function(i, tweet) {
var profilePicture = tweet.profile_image_url;
var userLink = tweet.from_user;
var text = tweet.text;
text = text.linkify().atify().hashify();
var createdAt = new Date(tweet.created_at);
var myTweet = '' + userLink + ' ';
myTweet += text;
$(settings.tweetHolder).append('<li class="cycles">' + myTweet + '</li>');
});
var elements = $(settings.tweetHolder).children();
var timeOutStart = 5000;
function fader(elementId) {
setTimeout(function() {
$(elements[elementId]).fadeOut(settings.fadeSpeed, function() {
$(elements[elementId + 1]).fadeIn(settings.fadeSpeed);
});
}, timeOutStart * (elementId));
};
for (var j = 0; j < elements.length; j++) {
fader(j);
};
});
};
})(jQuery);
You need to parse the tweet content, find the urls and then put them in between yourself.
Unfortunately, at the moment, the search API doesn't have the facility to break out tweet entities (i.e., links, mentions, hashtags) like some of the REST API methods. So, you could either parse out the entities yourself (I use regular expressions) or call back into the rest API to get the entities.
If you decide to call back into the REST API, and once you have extracted the status ID from the search API results, you would make a call to statuses/show like the following:
http://api.twitter.com/1/statuses/show/60183527282577408.json?include_entities=true
In the resultant JSON, notice the entities object.
"entities":{"urls":[{"expanded_url":null,"indices":[68,88],"url":"http:\/\/bit.ly\/gWZmaJ"}],"user_mentions":[],"hashtags":[{"text":"wordpress","indices":[89,99]}]}
You can use the above to locate the specific entities in the tweet (which occur between the string positions denoted by the indices property) and transform them appropriately.
If you prefer to parse the entities yourself, here are the (.NET Framework) regular expressions I use:
Link Match Pattern
(?:<\w+.*?>|[^=!:'"/]|^)((?:https?://|www\.)[-\w]+(?:\.[-\w]+)*(?::\d+)?(?:/(?:(?:[~\w\+%-]|(?:[,.;#:][^\s$]))+)?)*(?:\?[\w\+%&=.;:-]+)?(?:\#[\w\-\.]*)?)(?:\p{P}|\s|<|$)
Mention Match Pattern
\B#([\w\d_]+)
Hashtag Match Pattern
(?:(?:^#|[\s\(\[]#(?!\d\s))(\w+(?:[_\-\.\+\/]\w+)*)+)
Twitter also provides an open source library that helps capture Twitter-specific entities like links, mentions and hashtags. This java file contains the code defining the regular expressions that Twitter uses, and this yml file contains test strings and expected outcomes of many unit tests that exercise the regular expressions in the Twitter library.
How you process the tweet is up to you, however I process a copy of the original tweet, and pull all the links first, replacing them in the copy with spaces (so as not to modify the string length.) I capture the start and end locations of the match in the string, along with the matched content. I then pull mentions, then hashtags -- again replacing them in the tweet copy with spaces.
This approach ensures that I don't find false positives for mentions and hashtags in any links in the tweet.
I slightly modified previous one. Nothing lefts after all tweets disappears one by one.
Now it checks if there is any visible tweets and then refreshes tweets.
(function($) {
$.socialFader = function(options) {
var settings = {
tweetHolder : null,
tweetCount : 99,
fadeSpeed : 500,
};
if (options) {
$.extend(settings, options);
};
var URL = "http://search.twitter.com/search.json?q=istanbul&rpp=" + settings.tweetCount + "&callback=?";
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
var r = '';
if (delta < 60) {
r = 'a minute ago';
} else if(delta < 120) {
r = 'couple of minutes ago';
} else if(delta < (45*60)) {
r = (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (90*60)) {
r = 'an hour ago';
} else if(delta < (24*60*60)) {
r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
r = '1 day ago';
} else {
r = (parseInt(delta / 86400)).toString() + ' days ago';
}
return r;
};
String.prototype.hashify = function() {
return this.replace(/#([A-Za-z0-9\/\.]*)/g, function(m) {
return '<a target="_new" href="http://twitter.com/search?q=' + m.replace('#','') + '">' + m + "</a>";
});
};
String.prototype.linkify = function(){
return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
return m.link(m);
});
};
String.prototype.atify = function() {
return this.replace(/#[\w]+/g, function(m) {
return '' + m + "";
});
};
$.getJSON(URL, function(JSON) {
$(settings.tweetHolder).find('li.cycles').remove();
$.each(JSON.results, function(i, tweet) {
var profilePicture = tweet.profile_image_url;
var userLink = tweet.from_user;
var text = tweet.text;
text = text.linkify().atify().hashify();
var createdAt = new Date(tweet.created_at);
var myTweet = '' + userLink + ' ';
myTweet += text;
$(settings.tweetHolder).append('<li class="cycles">' + myTweet + '</li>');
});
var elements = $(settings.tweetHolder).children();
var timeOutStart = 5000;
function fader(elementId) {
setTimeout(function() {
$(elements[elementId]).fadeOut(settings.fadeSpeed, function() {
$(elements[elementId + 1]).fadeIn(settings.fadeSpeed);
});
if (jQuery('#twitter ul li.cycles:visible').length==1) {
jQuery.socialFader({ tweetHolder:"#twitter ul", tweetCount:5 });
}
}, timeOutStart * (elementId));
};
for (var j = 0; j < elements.length; j++) {
fader(j);
};
});
};
})(jQuery);
jQuery(document).ready(function(){
jQuery.socialFader({ tweetHolder:"#twitter ul", tweetCount:5 });
});

Resources