These are chat archives for canjs/canjs

16th
Jan 2019
Ivo Pinheiro
@ivospinheiro
Jan 16 14:57
Hi guys!
In CanJS@5 how can add an event listener to an element of type "change.datetimepicker"?
With CanJS@3 I was doing on the controller with:
events: {
  "{element} div.date change.datetimepicker":function(element, event) {
  ...
  }
}
But it does not work anymore
Kevin Phillips
@phillipskevin
Jan 16 15:12
this would still work if this is a normal DOM event
but this is probably a jquery event
Matthew Phillips
@matthewp
Jan 16 15:13
ah, smart kevin
in that case i'd probably just use $('div.date').on('change.datepicker', fn) in the inserted event
and call it a day
or in the ViewModel connectedCallback actually
Kevin Phillips
@phillipskevin
Jan 16 15:15
yeah, that's probably how I would handle it also
Ivo Pinheiro
@ivospinheiro
Jan 16 15:15
I was trying to avoid that!
Probably it was working with CanJS@3 because it uses can-jquery right?
Kevin Phillips
@phillipskevin
Jan 16 15:15
I discussed some other strategies in https://youtu.be/w_LqYMSVYW8?t=1310
I think I mentioned this exact plugin
Matthew Phillips
@matthewp
Jan 16 15:17
yeah, or can-view-callbacks
the answer to every question is usually can-view-callbacks attrs
Kevin Phillips
@phillipskevin
Jan 16 15:18
especially when it comes to jquery plugins
Ivo Pinheiro
@ivospinheiro
Jan 16 15:24
In this case I'm using this plugin https://tempusdominus.github.io/bootstrap-3
And there is no way to configure the change eventListener on the plugin initialization
so I will add the event listener on connectedCallback
I was just trying to avoid to register and unregister the event listener
Thanks @phillipskevin and @matthewp
Kevin Phillips
@phillipskevin
Jan 16 15:27
it's a bigger change, but it might be worth it to wrap this plugin in an viewCallbacks.attr
and call the plugin and register the listener in that attr code
especially if you're using this plugin in multiple components
apsignifi
@apsignifi
Jan 16 17:09
can3 -> can4 (inserted -> connectedCallback):
  • the code in inserted relies on execution of another jquery code.
  • in can4, the code which I moved to connectedCallback is getting executed. however, the jquery piece of code isn't executing it seems.
  • Here is what I had:
    <script type="events">
    import platform from 'steal-platform';
    import 'jquery/';
      // modified from datatables.buttons.js to return full ajax response (no pagination)
      jQuery.fn.DataTable.Api.register( 'buttons.exportData()', function ( options ) { /* ...jquery code */ });
         export default{ inserted:function(){ /* .. code from inserted */} )
    I have moved the code from inserted to connectedCallback in the viewModel. tried putting the jquery code before the 'inserted code' - does not work.
apsignifi
@apsignifi
Jan 16 17:18
is can-3-4-compat usable in can5/done3 ?
Kevin Phillips
@phillipskevin
Jan 16 17:29
yes, it is
it's only a couple lines of code though
tried putting the jquery code before the 'inserted code' - does not work.
what doesn't work exactly?
apsignifi
@apsignifi
Jan 16 18:06
@phillipskevin :
/***/
jQuery.fn.DataTable.Api.register( 'buttons.exportData()', function ( options ) {
        if ( this.context.length ) {
            var config = $.extend( true, {}, {
                rows:           null,
                columns:        ':visible',
                modifier:       {
                    search: 'applied',
                    order:  'applied'
                },
                orthogonal:     'display',
                stripHtml:      true,
                stripNewlines:  true,
                decodeEntities: true,
                trim:           true,
                format:         {
                    header: function ( d ) {
                        return strip( d );
                    },
                    footer: function ( d ) {
                        return strip( d );
                    },
                    body: function ( d ) {
                        return strip( d );
                    }
                }
            }, options );

            var dt = new jQuery.fn.DataTable.Api(this.context[0]);

            var params = dt.ajax.params();
            delete params.length;
            delete params.start;

            var request = new XMLHttpRequest();
            request.open('GET', dt.ajax.url() + '?' + $.param(params), false);  // `false` makes the request synchronous
            request.send(null);

            var strip = function ( str ) {
                if ( typeof str !== 'string' ) {
                    return str;
                }

                // Always remove script tags
                str = str.replace( /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '' );

                if ( config.stripHtml ) {
                    str = str.replace( /<[^>]*>/g, '' );
                }

                if ( config.trim ) {
                    str = str.replace( /^\s+|\s+$/g, '' );
                }

                if ( config.stripNewlines ) {
                    str = str.replace( /\n/g, ' ' );
                }

                // removed for now
                //if ( config.decodeEntities ) {
                    //_exportTextarea.innerHTML = str;
                    //str = _exportTextarea.value;
                //}

                return str;
            };

            var header = dt.columns().indexes().map( function (idx) {
                if(dt.column(idx).visible()){ //considering only visible cells
                    var el = dt.column( idx ).header();
                    if(el.classList.contains('edit')){ //return if header contain class edit
                        return;
                    }

                    return config.format.header( el.innerHTML, idx, el );
                }
            }).toArray();

            header = header.filter(item => item !== undefined); //filter undefined data from header row  

            var footer = dt.table().footer() ?
                dt.columns().indexes().map( function (idx) {
                    if(dt.column(idx).visible()){
                        var el = dt.column( idx ).footer();
                        if(el.classList.contains('edit')){ //return if footer contain class edit
                            return;
                        }                        
                        return config.format.footer( el ? el.innerHTML : '', idx, el );
                    }
                }).toArray() :    null;

            if(footer != null){
                footer = footer.filter(item => item !== undefined);
            }

            var columns = [];
            $.each(dt.settings().init().columns, function(i, column){
                if(dt.column(i).visible()){
                    if(column.hasOwnProperty('className') && column.className == 'edit'){ //return if column contain class edit
                        return;
                    }
                    columns.push(column);
                }
            });

            var response = JSON.parse(request.responseText);
            var body = [];

            $.each(response, function(i, row) {
                var cells = [];

                $.each(columns, function(j, column) {
                    var str = column.data(row);                    
                    str = (str!=null && str != '') ? str.replace(/<\/?span[^>]*>/g,"") : ''; //filter span tag from column data 
                    cells.push(str || '');
                });

                body.push(cells);
            });

            return {body: body, header: header, footer: footer };
        }
    });
/***/
apsignifi
@apsignifi
Jan 16 18:20
here is the original code which uses inserted:
https://codeshare.io/G8Le3B
apsignifi
@apsignifi
Jan 16 18:30
lines 2 - 11 is the template ( imports packages for datatables to work)
lines 46 - 168 is the JQuery for DataTables.
lines 171 - 507 is the inserted function.
Kevin Carmona-Murphy
@kcarmonamurphy-tc
Jan 16 19:50

question about can-stache-bindings syntax. currently getting deprecation warnings that doing the following:

<componentName property="textLiteral" />

is deprecated as of version 4 and that I should instead do something like:

<componentName property:from="textLiteral" />

The problem is that textLiteral is not a property in my ViewModel, it's just a string I went to pass into the component.
I've looked everywhere, can't seem to find the solution to my problem. Help pls :)

Kevin Phillips
@phillipskevin
Jan 16 19:51
property:raw is what you're looking for
Kevin Carmona-Murphy
@kcarmonamurphy-tc
Jan 16 19:56
would be great if we were on version 5, but we're on 3. do you know of a solution for v3?
Kevin Phillips
@phillipskevin
Jan 16 19:58
I think property:from="'textLiteral'" is the only solution
Kevin Carmona-Murphy
@kcarmonamurphy-tc
Jan 16 20:06
ok that works. i think i may have discovered a bug. our original property name in the stache file was hyphen-cased, but in the .js file it was camelCased. I had to change stache to be camelCased in order it to work with the new propertyName:from="'textLiteral'" syntax