1

I'm trying to include Almende's Google Timelines (Link to documentation) and I'm having some trouble rendering the timeline after the first time. I'm using JSON to fill in the data which is computed inside the page controller. It works fine the first time but everytime I click on the update button the elements inside timeline don't appear. I know that the controller generated JSON is right but when I order the timeline to redraw It simply draw an empty timeline.

The visualforce page code:

<apex:page controller="GanttChartController" sidebar="false" id="thePage" docType="html-5.0">

<apex:includeScript id="a" value="https://www.google.com/jsapi" />
<apex:includeScript value="{!$Resource.GanttChart}"/>
<apex:includeScript value="{!URLFOR($Resource.GanttChart, '/timeline.js')}"  />
<apex:stylesheet value="{!URLFOR($Resource.GanttChart, '/timeline.css')}"  />

<script type="text/javascript">

    google.load("visualization", "1");

    // Set callback to run when API is loaded
    google.setOnLoadCallback(drawVisualization);

    var timeline ;

    // Called when the Visualization API is loaded.
    function drawVisualization() {

        // specify options
        var cenas = {!tableOptions};
        var options = [];
        options.push(cenas);

        var cenascenas = {!jsonTabela};
        var data = [];
        data.push(cenascenas);


        // Instantiate our timeline object.
        timeline = new links.Timeline(document.getElementById('mytimeline'));


        //Event Functions
        // Make a callback function for the select event
        var onselect = function (event) {
            var row = undefined;
            var sel = timeline.getSelection();
            if (sel.length) {
                if (sel[0].row != undefined) {
                    var row = sel[0].row;
                }
            }

            if (row != undefined) {
                var content = data.getValue(row, 2);
                document.getElementById("txtContent").value = content;

                //INSERT AJAX HERE!
                //alert("cenas1");
                //document.getElementById("info").innerHTML += "event " + row + " selected<br>";

            }
        };

        // callback function for the change event
        var onchange = function () {
            var sel = timeline.getSelection();
            if (sel.length) {
                if (sel[0].row != undefined) {
                    var row = sel[0].row;

                    //INSERT AJAX HERE!
                    //alert("cenas2");
                    //document.getElementById("info").innerHTML += "event " + row + " changed<br>";
                }
            }
        };


        // Draw our timeline with the created data and options
        timeline.setOptions(cenas);
        timeline.draw(cenascenas);

        google.visualization.events.addListener(timeline, 'select', onselect);
        google.visualization.events.addListener(timeline, 'change', onchange);

        var newStartDate = dateFormat({!dataInicioJson});
        var newEndDate   = dateFormat({!dataFimJson});
        timeline.setVisibleChartRange(newStartDate, newEndDate, true);

    }

    function updateChart(paramOne){

        var optionsTmp = {!tableOptions};
        var options = [];
        options.push(optionsTmp);

        var dataTmp = [{ "start" : new Date(2015,01,16,00,00,01), "end" : new Date(2015,01,28,23,59,59), "content" : "Sprint 4", "group" : "Sprint3" }];
        //var dataTmp = paramOne;
        var data = [];
        data.push(dataTmp);

        alert(data + '');

        timeline = new links.Timeline(document.getElementById('mytimeline'));

        var newStartDate = dateFormat({!dataInicioJson});
        var newEndDate   = dateFormat({!dataFimJson});

        //timeline.setData(data);
        //timeline.setVisibleChartRange(newStartDate, newEndDate, true);

        //timeline.setOptions(options);
        //timeline.redraw();
        document.getElementById('mytimeline') = timeline;

        //actualizarTextojs();
    }

    // Format given date as "yyyy-mm-dd hh:ii:ss"
    // @param datetime   A Date object.
    function dateFormat(date) {
        var datetime =   date.getFullYear() + "-" +
               ((date.getMonth()   <  9) ? "0" : "") + (date.getMonth()) + "-" +
               ((date.getDate()    < 10) ? "0" : "") +  date.getDate() + " " +
               ((date.getHours()   < 10) ? "0" : "") +  date.getHours() + ":" +
               ((date.getMinutes() < 10) ? "0" : "") +  date.getMinutes() + ":" +
               ((date.getSeconds() < 10) ? "0" : "") +  date.getSeconds();
        return datetime;
    }

    function setTime() {
        if (!timeline) return;

        var newStartDate = new Date(document.getElementById('startDate').value);
        var newEndDate   = new Date(document.getElementById('endDate').value);
        timeline.setVisibleChartRange(newStartDate, newEndDate);
    }
</script>

<apex:form >

    <apex:actionFunction name="actualizarTextojs" reRender="timelinePanel" />

    <apex:actionFunction name="activatePopupOne" reRender="popupOneId" >
        <apex:param name="idPopup" value=""/>
    </apex:actionFunction>
    <apex:pageBlock >
        <apex:pageBlockSection title="Filtros" columns="1">
            <apex:commandButton value="Update" action="{!configureTableOptions}" oncomplete="updateChart('{!jsonTabela}');"/>

        </apex:pageBlockSection>
    </apex:pageBlock>

    <apex:pageBlock >
        <apex:outputPanel id="timelinePanel" >
            <div id="mytimeline">
            </div>
                <apex:outputText value="{!jsonTabela}" />
        </apex:outputPanel>
    </apex:pageBlock>

</apex:form>

The controller code:

public with sharing class GanttChartController {

public String jsonTabela {get; set;}
public String tableOptions {get; set;}

private map<String, Sprint__c> mapIdESprint;
public list<String> lstSprintSelecionados {get; set;}
public list<SelectOption> lstSprintPicklist {get; set;}

private static String queryBaseSprint = 'SELECT Data_fim__c,Data_inicio__c,Grupo_Sprint__c,Id,Name,Observacoes__c,OwnerId,Status__c,Total_Balance__c,Total_Points__c,Total_Remaining_Availability__c,Total_Remaining__c,Total_Resource_Availability__c,Total_Spent__c FROM Sprint__c';


public GanttChartController() {

    //Sprints
    list<Sprint__c> lstSprintsAux = Database.query(queryBaseSprint + ' ORDER BY Name ASC NULLS LAST');
    mapIdESprint = new map<String, Sprint__c>();
    lstSprintSelecionados = new list<String>();
    lstSprintSelecionados.add('all');
    lstSprintPicklist = new list<SelectOption>();
    lstSprintPicklist.add(new SelectOption('all','All'));
    for(Sprint__c sprintAux : lstSprintsAux){
        mapIdESprint.put(sprintAux.Id, sprintAux);
        lstSprintPicklist.add(new SelectOption(sprintAux.Id,sprintAux.Name));
    }

    configureTableOptions();


}

public void configureTableOptions(){    

    tableOptions = '{ "width": "99%", "editable": true, "layout": "box", "stackEvents" : false, "groupsOrder" : false, "axisOnTop" : true}';

    jsonTabela =    '[' ;

    //Inserir o sprint
    String jasonSprints = '';
    if(lstSprintSelecionados != null && !lstSprintSelecionados.isEmpty()){
        System.debug(lstSprintSelecionados);
        if(lstSprintSelecionados.get(0) == 'all'){
            //jsonTabela += ',';
            for(Sprint__c sprintAux : mapIdESprint.Values()){
                String content = ' <button > ' + sprintAux.Name + ' </button>';


                jasonSprints += '{ "start" : new Date('+ this.convertDate(sprintAux.Data_inicio__c) + ',00,00,01), "end" : new Date(' + this.convertDate(sprintAux.Data_fim__c) + ',23,59,59), "content" : \"' + content + '\", "group" : "Sprint" , "editable" : false },';
            }
        }else{
            Sprint__c sprintTmp = null;
            for(String strSprintAux : lstSprintSelecionados){
                if(mapIdESprint.containsKey(strSprintAux)){
                    sprintTmp = mapIdESprint.get(strSprintAux);
                    jasonSprints += '{ "start" : new Date('+ this.convertDate(sprintTmp.Data_inicio__c) + ',00,00,01), "end" : new Date(' + this.convertDate(sprintTmp.Data_fim__c) + ',23,59,59), "content" : "' + sprintTmp.Name + '", "group" : "Sprint", "editable" : false },';
                }
            }
        }
    }
    if(jasonSprints != ''){
        jsonTabela += jasonSprints.substring(0, jasonSprints.length() - 1) + '';
    }

    jsonTabela += ']';

}

public void atualizarTexto(){

}

public String convertDate(Date d){
    String dt = d.year() + ',';
    Integer month = d.month() - 1;
    if(month < 10){
        dt += '0' + month + ',';
    }else{
        dt += month + ',';
    }

    Integer day =  d.day();
    if(day<10){
        dt += '0' + day;
    }else{
        dt += day;
    }

    return dt;
}

}

Does anyone have idea why this doesn't work? (Sorry, some comments are in portuguese)

Thanks in advance

  • 1
    Never use commandButton with both action and oncomplete parameters. It doesn't always work and the order of execution is not guaranteed. I reckon your oncomplete method executes and then your action finishes and rerenders the whole form. Try use a normal HTML input button with an onclick event that will call an actionFunction method which then will also execute your oncomplete method. – Boris Bachovski Apr 27 '15 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.