Trigger cocoon add_association from javascript - ruby-on-rails

I am using cocoon and I want to automatically add a child record when a date(can be multiple dates) in a date picker is selected.
I can trap the date selections in coffeescript like this, but I don't know how to get a child record added through cocoon i.e. by emulating what happens when the link_to_add_association is fired.
$(".form_multidate").datepicker().on 'changeDate', (e) -> alert(e.dates)
the cocoon setup is a standard nested form, no tricks, working fine on the page.
EDIT: Code mentioned in comment re binding calendar:
$(document).ready(function() {
$('#other_request_details')
.bind('cocoon:after-insert', function() {
return $('.datepicker-single').datepicker({
dateFormat: "DD, dd M yy"
});
});
});

Calling a JS function in order to add a new record with Cocoon is not possible. The only thing you can do is trigger the click event of the add association button.
If you see Cocoon's library code you will see that all new record functionality is bound to the click button
$(document).on('click', '.add_fields', function(e) {
e.preventDefault();
var $this = $(this),
assoc = $this.data('association'),
assocs = $this.data('associations'),
content = $this.data('association-insertion-template'),
insertionMethod = $this.data('association-insertion-method') || $this.data('association-insertion-position') || 'before',
insertionNode = $this.data('association-insertion-node'),
insertionTraversal = $this.data('association-insertion-traversal'),
count = parseInt($this.data('count'), 10),
regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'),
regexp_underscord = new RegExp('_new_' + assoc + '_(\\w*)', 'g'),
new_id = create_new_id(),
new_content = content.replace(regexp_braced, newcontent_braced(new_id)),
new_contents = [];
if (new_content == content) {
regexp_braced = new RegExp('\\[new_' + assocs + '\\](.*?\\s)', 'g');
regexp_underscord = new RegExp('_new_' + assocs + '_(\\w*)', 'g');
new_content = content.replace(regexp_braced, newcontent_braced(new_id));
}
new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
new_contents = [new_content];
count = (isNaN(count) ? 1 : Math.max(count, 1));
count -= 1;
while (count) {
new_id = create_new_id();
new_content = content.replace(regexp_braced, newcontent_braced(new_id));
new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
new_contents.push(new_content);
count -= 1;
}
var insertionNodeElem = getInsertionNodeElem(insertionNode, insertionTraversal, $this)
if( !insertionNodeElem || (insertionNodeElem.length == 0) ){
console.warn("Couldn't find the element to insert the template. Make sure your `data-association-insertion-*` on `link_to_add_association` is correct.")
}
$.each(new_contents, function(i, node) {
var contentNode = $(node);
insertionNodeElem.trigger('cocoon:before-insert', [contentNode]);
// allow any of the jquery dom manipulation methods (after, before, append, prepend, etc)
// to be called on the node. allows the insertion node to be the parent of the inserted
// code and doesn't force it to be a sibling like after/before does. default: 'before'
var addedContent = insertionNodeElem[insertionMethod](contentNode);
insertionNodeElem.trigger('cocoon:after-insert', [contentNode]);
});
});

Related

How can we do date highlight which we particular disabled using jquery in ui datepicker

Here is my code as below, Please help me to find out solution for add highlight on those dates which I particularly disabled and Sundays.
And Do not want to highlight disabled previous dates from current date.
In this how can add highlights on particular dates which I disabled.
$(document).ready(function(){
jQuery(function() {
var blockedDates = ["12/20/2022", "12/28/2022", "12/24/2022", "12/19/2022"];
var dateFormat = "yy-mm-dd";
$( "#datepicker" ).datepicker({
dateFormat:'yy-mm-dd',
minDate: 0,
daysOfWeekDisabled: [0, 6],
onSelect: function(dateStr) {
var _frmdate = $.trim($(this).val());
jQuery("#blockModalDateItem").modal("show");
jQuery("#bk_blockdt").val(_frmdate);
jQuery(".status_msg").html("");
},
beforeShowDay: function(date){
show = true;
if(date.getDay() == 0 ){show = false;}
for (var i = 0; i < blockedDates.length; i++) {
if (new Date(blockedDates[i]).toString() == date.toString()) {show = false;}
}
var display = [show,'',(show)?'':'Block Settlement Date']; //Disabled Particular dates & all Sundays.
return display;
}
});
});
You can use CSS to apply styles to disabled dates. Specifically targeting dates with title="Block Settlement Date"
.ui-datepicker-unselectable.ui-state-disabled[title="Block Settlement Date"] {
background:red;
}
Thank you to all, For giving precious time to help my queries.
But I found my custom solution for my problem & I would like to share here may this will help to others.
New changes added to datepicker in beforeshowday is here, in this i have added custom class.
$(document).ready(function(){
jQuery(function() {
var blockedDates = ["12/20/2022", "12/28/2022", "12/24/2022", "12/19/2022"];
var dateFormat = "yy-mm-dd";
$( "#datepicker" ).datepicker({
dateFormat:'yy-mm-dd',
minDate: 0,
daysOfWeekDisabled: [0, 6],
onSelect: function(dateStr) {
var _frmdate = $.trim($(this).val());
jQuery("#blockModalDateItem").modal("show");
jQuery("#bk_blockdt").val(_frmdate);
jQuery(".status_msg").html("");
},
beforeShowDay: function(date){
show = true;
if(date.getDay() == 0 ){show = false;}
for (var i = 0; i < blockedDates.length; i++) {
if (new Date(blockedDates[i]).toString() == date.toString()) {show = false;}
}
var display = [show,'highlight-bkdate',(show)?'':'Block Settlement Date']; //Disabled Particular dates & all Sundays.
return display;
}
});
});
In this class i have applied some css for giving highlight purpose.
.highlight-bkdate span {
color: #fff!important;
background-color: red!important;
border: 3px solid #191970!important;
}
Now this state it will highlight all disabled dates, Now I want to only particular dates & sunday should highlight.
So, I called this function after datepicker load. In this I again removed class on those dates which I do not want to highlight.
setTimeout(removeClassHigh, 50);
function removeClassHigh(){
var blockedDates = ["12/20/2022", "12/28/2022", "12/24/2022", "12/19/2022"];
var dayNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
var currentYear = jQuery(".ui-datepicker-year").text();
var currentMonth = jQuery(".ui-datepicker-month").text();
var oneMonth = 1;
var dat = new Date('1 ' + currentMonth +' ' +currentYear);
var monthNo = dat.getMonth();
oneMonth += Number(monthNo);
var f1 = 1;
var d = new Date();
var day = d.getDate();
$('.ui-state-default').each(function () {
var checkCurrentDt = new Date(oneMonth+'/'+f1+'/'+currentYear);
var checkThisDay = checkCurrentDt.getDay();
var checkThisDate = String(checkCurrentDt.getDate()).padStart(2, '0');
if(day==f1){
return false;
}else{
if(dayNames[checkThisDay]!="Sunday"){
if (jQuery.inArray(oneMonth+'/'+checkThisDate+'/'+currentYear, blockedDates) === -1) {
$(this).parent().removeClass('highlight-bkdate');
}
}
}
f1++;
});
}
So in this way found this solution.
And Result as below:
Thank you to all..!!
Have a great day :)

Open infowindow with sidebar on Google Fusion Table

For the life of me, I can't get this map to open infowindows on the sidebar link clicks: http://web.redding.com/static/redd/asphalt/prod/xmas-lights-2014-complex.html
Here's the fusion table: https://www.google.com/fusiontables/DataSource?docid=1WrvKdTypAmZozAIVeOw4vBX2g1hPInyVyuqn8GUM
Which looks like this (CSV):
Location,Description,Photo,Winner,Name
"1101 Twin View Boulevard, Redding CA",Redding's finest media organization with decades of experience & class.,http://mediaassets.redding.com/photo/2014/03/15/youthcamp17b-01_3471502_ver1.0.jpg,,The Record Searchlight
"1500 Court Street, Redding CA",Shasta Courthouse,,,
"777 Cypress Avenue, Redding CA",City Hall,,,
All I want to do is be able to click on the links in the sidebar and have the associated infowindow open on the map.
I'm new to javascript so I wouldn't be surprised if there's something obvious I'm overlooking.
Code from the linked page:
function createSidebar() {
//set the query using the parameter
var query = new google.visualization.Query(queryText);
var queryText = encodeURIComponent("SELECT 'Name','Description' FROM 1uQLxgNdNR_etBFP8O_0YNDA38PqyZB3NidIJfsgX");
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
//set the callback function
query.send(getData);
}
function myFTclick(row) {
var Name = FTresponse.getDataTable().getValue(row,0);
var Description = FTresponse.getDataTable().getValue(row,1);
var Location = FTresponse.getDataTable().getValue(row,2);
var Photo = FTresponse.getDataTable().getValue(row,5);
var Winner = FTresponse.getDataTable().getValue(row,7);
var position = new google.maps.LatLng(lat, lng);
// Set up and create the infowindow
if (!infoWindow) infoWindow = new google.maps.InfoWindow({});
var content = '<div class="FT_infowindow">' + name;
if (Description) content += '<br>'+Description;
if (Location) content += '<br>'+Location;
if (Photo) content += '<br>'+Photo;
if (extraContent) content += "<br>["+extraContent+"]";
content += '<br>'+'zoom in';
content += '</div>';
infoWindow.setOptions({
content: content,
pixelOffset: null,
position: position
});
// Infowindow-opening event handler
infoWindow.open(map);
}
var FTresponse = null;
//define callback function, this is called when the results are returned
function getData(response) {
if (!response) {
alert('no response');
return;
}
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
FTresponse = response;
//for more information on the response object, see the documentation
//http://code.google.com/apis/visualization/documentation/reference.html#QueryResponse
numRows = response.getDataTable().getNumberOfRows();
numCols = response.getDataTable().getNumberOfColumns();
//concatenate the results into a string, you can build a table here
fusiontabledata = "<table><tr>";
fusiontabledata += "<th>" + response.getDataTable().getColumnLabel(1) + "</th>";
fusiontabledata += "</tr><tr>";
for(i = 0; i < numRows; i++) {
fusiontabledata += "<td><a href='javascript:myFTclick("+i+")'>"+response.getDataTable().getValue(i, 1) + "</a></td>";
fusiontabledata += "</tr><tr>";
}
fusiontabledata += "</table>"
//display the results on the page
document.getElementById('sidebar').innerHTML = fusiontabledata;
}
You have a javascript error in your code, look at the javascript console: Uncaught Error: Invalid column index 2. Should be an integer in the range [0-1].
Your query only includes two columns from the table:
var queryText = encodeURIComponent("SELECT 'Name','Description' FROM 1uQLxgNdNR_etBFP8O_0YNDA38PqyZB3NidIJfsgX");
Which means you can't get any columns beyond 0 and 1, so this will not work:
function myFTclick(row) {
var Name = FTresponse.getDataTable().getValue(row,0);
var Description = FTresponse.getDataTable().getValue(row,1);
var Location = FTresponse.getDataTable().getValue(row,2);
var Photo = FTresponse.getDataTable().getValue(row,5);
var Winner = FTresponse.getDataTable().getValue(row,7);
You need to include those in your query:
var queryText = encodeURIComponent("SELECT 'Name','Description','Location','Photo','Winner' FROM 1uQLxgNdNR_etBFP8O_0YNDA38PqyZB3NidIJfsgX");
Then access them in that order:
function myFTclick(row) {
var Name = FTresponse.getDataTable().getValue(row,0);
var Description = FTresponse.getDataTable().getValue(row,1);
var Location = FTresponse.getDataTable().getValue(row,2);
var Photo = FTresponse.getDataTable().getValue(row,3);
var Winner = FTresponse.getDataTable().getValue(row,4);

RemoteFunction inside jQDateRangeSlider's UserValuesChanged Event

I have one drop-down and a jQDateRangeSlider(a jQuery widget) in index.gsp of my Grails app.I am posting the value selected in the dropdown and the range selected over the slider to a query in my controller using remoteFunction.I want these three values(2 values from the slider and one value from the drop-down) to be posted to the controller when either of the following events occur:
Drop-down changes
Values over the slider change
The remoteFunction works fine from the onChange of the drop-down but when I replicate the remoteFunction inside the UserValuesChanged block of the slider, it throws an error.This is how my code looks like:
Controller
class PgtypController {
def ajaxGetMv = {
def pgtyp = Pgtyp.executeQuery("select p.date_hour ,p.visits, p.mv, p.browser,p.pagetype,p.platform,p.device,p.time_period from Pgtyp p where p.mv = ? and p.date_hour >= ? and p.date_hour <= ? order by col_0_0_ asc ",[ params.mv ] + params.list( 'date_hour' ))
render pgtyp as JSON
}
def dataSource
def datejson = {
def sql = new Sql(dataSource)
def rows = sql.rows("select min(date_hour) as a , max(date_hour) as b from pgtyp")
sql.close()
render rows as JSON
}
def index() {
}
GSP
<form>
<g:select from="['AFFILIATES', 'CSE','DISPLAYADS','EMAIL','MOBILEWEB','OTHERS','ORGANIC','SEO', 'SEM']" name="mv" id = "mv"
onchange="${remoteFunction(
controller:'Pgtyp',
action:'ajaxGetMv',
params:'\'mv=\' + escape(this.value)+\'&date_hour=\'+ z+\'&date_hour=\'+ b',
//params:'\'mv=\'+this.value',
onSuccess: 'printpgtyp(data)')}"
></g:select>
</form>
<script>
dataFile = "http://localhost:8080/marchmock2/Pgtyp/datejson";
d3.json(dataFile, function(error,data) {
if (data)
dataset = data;
var min = dataset[0].a;
var min2 = new Date(min);
var max = dataset[dataset.length - 1].b;
var max2 = new Date(max);
function addZero(val) {
if (val < 10) {
return "0" + val;
}
return val;
}
var s = $j("#slider").dateRangeSlider({
bounds: {
"min": min2,
"max": max2
},
range: {
min: {
hours: 1
}
},
formatter:function(val){
var m = moment(val);
return m.format("DD/MM/YYYY HH:00:00 ");
},
defaultValues:{
min: min2,
max: max2
}
});
x = (s.dateRangeSlider("values").min);
x.setMinutes(0);
x.setSeconds(0);
z = x.getFullYear()+'-'+(x.getMonth()+1)+ '-'+x.getDate()+' '+x.getHours()+':'+'00'+':'+'00' ;
var y = (s.dateRangeSlider("values").max);
y.setMinutes(0);
y.setSeconds(0);
b = y.getFullYear()+'-'+(y.getMonth()+1)+ '-'+y.getDate()+' '+y.getHours()+':'+'00'+':'+'00' ;
$j('#slider').on("userValuesChanged",function (e, data) {
var x = datavalues.min;
x.setMinutes(0);
x.setSeconds(0);
z = x.getFullYear()+'-'+(x.getMonth()+1)+ '-'+x.getDate()+' '+x.getHours()+':'+'00'+':'+'00' ;
var last = data.values.max;
last.setMinutes(0);
last.setSeconds(0);
b = last.getFullYear()+'-'+(last.getMonth()+1)+ '-'+last.getDate()+' '+last.getHours()+':'+'00'+':'+'00' ;
${remoteFunction(
controller:'Pgtyp',
action:'ajaxGetMv',
params:'\'mv=\' +$(\'mv\').value+\'&date_hour=\'+ z+\'&date_hour=\'+ b',
onSuccess: 'printpgtyp(data)')}
})
});
function printpgtyp(data)
{
console.log(data)
console.log(data.length)
}//end of printpgtyp
</script>
This however gives an error like this:
Uncaught SyntaxError: Unexpected token &
Can anyone tell me where exactly am I going wrong? If the code is working fine inside onChange of select tag then why am I getting this error inside UserValuesChanged of the slider?

dynamically making textarea ckeditor

When i try to make these dynamically made textareas into CEditor fields i get the error:
TypeError: b is undefined
my code:
var input = $("<textarea>").addClass("textAreaClassTest");
//input.setAttribute("id", "como");
//input.setIdAttribute("id", "como");
//input.ID = 'como';
CKEDITOR.replace('como');
item.append(input);
//CKEDITOR.replace('como');
return item;
i cant seem to give the textarea an id - any id's :)
I'm assuming you're using jQuery and only working with 1 or more text areas at a time. So you can get the text areas and assign them ids and use them as below.
//select all text areas
var input = $("textarea");
var list = new Array();
var count = 0;
input.each(function () {
count++;
$this = $(this);
$this.attr("id", "como" + count);
console.log('id is "' + $this.attr("id") + '" and text is "' + $this.text() + '"');
CKEDITOR.replace($this.attr("id"));
list.push($this.attr("id"));
});
//return the list of replaced text area ids
return list;

Amcharts rendering data incorrectly

I have a setup where I am using amcharts that is feed data via appendData from an AJAX call. The call goes to a URL which simply renders the Time.now as the X and 8 lines using the function 2cos(x/2)+2ln (ln is the line number). AJAX request is made every 1 second.
The backend is always correct and always returns a single point, unless it is a duplicate X in which it throws an error. The error causes not to complete and therefore not call appendData.
Anybody have any idea what is going wrong with amcharts? It seems to be an issue only with appendData (which I need to simulate a sliding window).
The Javascript code is below. It assumes that the page creates a line chart with 8 points graphs and passes it to setup_chart_loader. Netcordia.rapid_poller.updateChart is used to update the chart using the Ajax request
Ext.ns("Netcordia.rapid_poller");
Netcordia.rapid_poller.refresh_rate = 1; //seconds
Netcordia.rapid_poller.pause = false; //causes the AJAX to suspend
Netcordia.rapid_poller.chart = null;
Netcordia.rapid_poller.stop = false;
/* This function does everything that is required to get the chart data correct */
Netcordia.rapid_poller.setup_chart_loader = function(chart){
assert(Netcordia.rapid_poller.displaySizeInMinutes,"No display size");
assert(Netcordia.rapid_poller.delta_url, "Data URL is empty");
assert(Netcordia.rapid_poller.delta_params, "No Data params");
if(typeof(chart) !== 'object'){
chart = document.getElementById(chart);
}
Netcordia.rapid_poller.chart = chart;
// 5 seconds raw polling
var maxPoints = Netcordia.rapid_poller.displaySizeInMinutes * 60 / 5;
var count = 0;
var lastUpdate = '';
debug("max number of points: "+maxPoints);
debug('creating updateChart function');
Netcordia.rapid_poller.updateChart = function(){
debug("Sending Data request");
var params = {last: lastUpdate, max: 1}; //maxPoints};
//I have to do this otherwise amcharts get a lot of data and only renders
// one item, then the counts is off
if(lastUpdate === ''){params['max'] = maxPoints;}
if (Netcordia.rapid_poller.pause){
alert("pausing");
params['historical'] = 1;
params['max'] = maxPoints;
}
Ext.apply(params, Netcordia.rapid_poller.delta_params);
//this might need to be moved to within the Ajax request
// incase things start piling up
if(!Netcordia.rapid_poller.stop){
setTimeout(Netcordia.rapid_poller.updateChart,1000*Netcordia.rapid_poller.refresh_rate);
} else {
debug("skipping next poll");
return;
}
Ext.Ajax.request({
url: Netcordia.rapid_poller.delta_url,
baseParams: Netcordia.rapid_poller.delta_params,
params: params,
success: function(response){
//if(Netcordia.rapid_poller.pause){
// debug("Data stopped");
// return;
//}
var json = Ext.util.JSON.decode(response.responseText);
lastUpdate = json.lastUpdate;
if( json.count === 0 ){
debug("no data to append");
return;
}
debug("appending "+json.count);
var remove = (count + json.count) - maxPoints;
if(remove <= 0){ remove = 0; }
count += json.count;
if(count > maxPoints){ count = maxPoints; }
debug("removing "+remove);
debug("count: "+count);
if(Netcordia.rapid_poller.pause){
alert("Pausing for historical");
//append a zero point and delete the existing data
// amcharts can leak extra points onto the screen so deleting
// twice the number is
chart.appendData("00:00:00;0;0;0;0;0;0;0;0",(count*2).toString());
count = json.count;
remove = 1;
Netcordia.rapid_poller.stop = true;
}
chart.appendData(json.lines.toString(),remove.toString());
}
});
};
};
The rails code that returns the data is as follows:
def get_delta
max = 1
begin
current = Time.parse(params[:last])
rescue
current = Time.now
end
if params[:historical]
max = params[:max].to_i || 10
current = Time.at(current.to_i - (max/2))
end
logger.info(current.to_i)
logger.info(max)
n = current.to_i
m = n+max-1
data = (n..m).collect do |x|
logger.info "For Point: #{x}"
point = Math.cos(x/2)
data = [Time.at(x).strftime("%H:%M:%S")]
for i in (1..8)
data.push(2*point+(2*i));
end
data.join(";")
end
render :json => {count: data.size, lastUpdate: Time.now.strftime('%Y-%m-%d %H:%M:%S'), lines: data.join("\n")}
end
Seems to be a bug in Amcharts itself.
Forum Post has the developer's answer.

Resources