Saving the Input Values

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi

Is there an option of saving the input values in the App?

I have 3 input parameters , when shared with the user , can he save the selected filter values so that each time he opens the app, he look at the same filter selections?

Mine is presto 3.1

Thank you

Radhika

0
Your rating: None
smitchell
smitchell's picture
User offline. Last seen 2 weeks 5 days ago. Offline
Joined: 08/29/2008
Points: 34

Users can do this in the Presto App Store. When they add an App to "My Apps", they can set specific values for inputs. When they run it from My Apps, they see the values they chose. They can change those values and it only affects their personal version of the App.

Sara, technical writer/jackbe

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Thank you ! , So how about the users who does not have access to App Store.?

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 If you want end users to be able to save their inputs then the easiest way would be to use browser cookies, if the end user is an authenticated Presto user then another option would be to save the form inputs to presto as Presto User Attributes.

The following code can be used to extend a Presto.BasicApp, using the same technique described here http://www.jackbe.com/enterprise-mashup/forum/hidding-input-filters, to get/set App properties using cookies:

 

Presto.BasicApp.prototype.onLoad = function(app){

    var props, cookie = app.id + '-props', cookies = new Presto.Util.CookieProvider(),

    getProperties = function(){
        props = cookies.get(cookie);
        if(props){
            var names = app.getPropertyNames();
            names.each(function(name){
                if(props[name]){
                    // update app with stored property value..

                    app.setPropertyValue(name, props[name]);

                    // and update input form with stored value..

                    jQuery(app.rootElement).find('.form-field[name='+name+']').val(props[name]);
                }
            });
        }
        return props;
    },

    setProperties = function(){
        var prop, value, changed = false,
        names = app.getPropertyNames();
        names.each(function(name){
            prop = app.getProperty(name);

            // if property is visible and is an input property..

            if(!prop.hidden && prop.isinput){
                value = app.getPropertyValue(name);

                // and if the property value has changed..

                if(props[name] != value){
                    changed = true;
                    props[name] = value;
                }
            }
        });

        // if one or more properties have chnaged then save as cookie

        if(changed){
            cookies.set(cookie, props);
        }
    },

    // onload we will check if properties are stored

    props = getProperties() || {};

    // each time input form apply button is clicked we will check to
    // see if we need to store any input properties

    jQuery(app.rootElement).find('button').click(setProperties);

}

 

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi Jeremy

Let me put my requirement a bit in detail, here is the sample igoogle finance widget ,www.google.com/ig/adde

This is what i want to replicate in my apps , with the code you gave to hide and show the filters worked excellent , now i want to save the value i selected in the filters , could you please share me an App and App editor script which uses the above code including the code to show/hide input filters.

I am just a complete fresher to Java coding , all we want is to set up an app with these features(as in google finance widget) so that going ahead our team can use the same template for all our applications

Thank you

Radhika

 

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

Here is a link to an extended Presto.BasicApp which uses teh above code and teh code detailed on the earlier post.

Here it is in the editor:

http://prestocloud.jackbe.com/prestohub/app-editor.html?mid=Custom_Local_Search

and the app can be viewed here:

http://prestocloud.jackbe.com/prestohub/applauncher.html?mid=Custom_Local_Search

I'll also attached a downloadable copy of the app which you can then load into App Editor by clicking "New" and uploading the zip file from your local filesystem.

Here is the full javascript code used to extend the App :

 

var interval = setInterval(function(){
    if(Presto && Presto.BasicApp && typeof Presto.BasicApp == 'function'){
        clearInterval(interval);

        Presto.BasicApp.prototype.onLoad = function(app){

            var root = jQuery(app.getRootElement()),
            cookie = app.id + '-props', cookies = new Presto.Util.CookieProvider(),
            props,

            getProperties = function(){
                props = cookies.get(cookie);
                if(props){
                    var names = app.getPropertyNames();
                    names.each(function(name){
                        if(props[name]){
                            // update app with stored property value..
                            app.setPropertyValue(name, props[name]);
                            // and update input form with stored value..
                            root.find('.form-field[name='+name+']').val(props[name]);
                        }
                    });
                }
                return props;
            },

            setProperties = function(){
                var prop, value, changed = false,
                names = app.getPropertyNames();
                names.each(function(name){
                    prop = app.getProperty(name);
                    // if property is visible and is an input property..
                    if(!prop.hidden && prop.isinput){
                        value = app.getPropertyValue(name);
                        // and if the property value has changed..
                        if(props[name] != value){
                            changed = true;
                            props[name] = value;
                        }
                    }
                });

                // if one or more properties have chnaged then save as cookie
                if(changed){
                    cookies.set(cookie, props);
                }
            },

            // onload we will check if properties are stored

            props = getProperties() || {},

            basicAppInput = root.find('div.basic-app-input'),
            inputForm = basicAppInput.find('div.form-fields'),
            header = root.parentsUntil('div.app-main').parent().find('div.app-header'),
            headerLeft = header.find('h2.left'),
            headerRight = header.find('div.right'),

            // arrange input form horizontally..
            inputs = inputForm.find('div.fieldset');
            inputForm.css({
                'position':'relative', 
                'top':'0px', 
                'left':'0px'
            });

            inputs.each(function(index){
                jQuery(this).css({
                    position: 'absolute',
                    top: '0',
                    left: (index * 200) + 'px'
                });
            });

            inputForm.find('button').parent().css('padding', '60px 0 0 4px');
            jQuery('<span/>').addClass('app-inputs').prependTo(headerRight);
            jQuery('<span/>').addClass('app-input-info').css({
                'font-style':'normal',
                'font-size':'13px',
                'padding-left': '20px'
            }).appendTo(headerLeft);

            jQuery('<a/>').addClass('action-app-embed app-action publish-link')
            .attr({
                'title':'Show/Hide Input Form',
                'href':'javascript:void(0);'
            }).css('background-position', '-120px 0')
            .appendTo(headerRight.find('span.app-inputs')).click(function(e){
                inputForm.toggle();
            });

            jQuery(root).find('.action-apply').click(function(){
                var inputs = '';
                inputForm.find('div.fieldset').each(function(index){
                    if(index > 0)inputs += ', ';
                    inputs += jQuery(this).find('div').first().html() + ' : ' + jQuery(this).find('.form-field').first().val();
                });

                headerLeft.find('span.app-input-info').html(inputs);
                inputForm.hide();

                // finally, each time input form apply button is clicked we will check to
                // see if we need to store any input properties
                setProperties();
            });
            
            // hide input form and submit form :
            inputForm.hide();
            root.find('form').submit();

};
}
}, 100);

 

 

 

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi Jeremy

This works pretty good for the saving of the input parameters , please take a look at the screen cast below , the igoogle widget has a small drop down where you can give the input parameter value and click on save , its not necessary that i should have the same functionality , as we already have the apply button and the code to save the input values , the only thing i would want to see now would be the default data when the app is opened, currently my app shows input parameters when opened , can we set to display the views first then allow the user to enter the input values ?

However i have set up some default values in the mashup for input parameters, so just wanted to show the data first as in the video below  ...

http://screencast.com/t/uyxFyBSQ5tJ

Please advice

Thank you

Radhika

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi Jeremy

I have created the mashboard app using the 2 column app , and unchecked the option of hiding the title bar , which is supposed to have the little toggle button you gave me to show/hide the input values , when i use the same app in the mashboard i am unable to see that option , could you please help me in figuring out this , Please let me know if i am missing something here , this is my first mashboard app,

here is the video of what i am seeing

http://screencast.com/t/nUCV7eSB

Thank you!

 

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 You can force the app to apply the initial settings and hide the input form by adding the following couple of lines at the end of the onLoad method :

 

   inputForm.hide();
   root.find('form').submit();

 

 

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

A composite App created in Mashboard is called a Workspace, or Workspace App. The App Header Area, to which we added the show/hide form toggle button icon, is not available in workspace apps, workspaces provide their own contained App header, as part of the APp container.

The custom code we've been using is not suitable if the App is to be used as part of a Workspace App, the button icon is not suitable and we need to handle the different type of header.

One way to do it would be to have a control which is rendered as part of the App rather than in the header area, so it wouldnt matter if the app is rendered standalone or as part of a workspace.

Probably easiest and best solution would be to take control of the collapse/expand button icon and use it to toggle the display the App input form. We could do this, but the solution is made slightly more complicated by the fact that when the Workspace is rendered in mashboard it is implemented using Sencha Ext-js framework, but when the Workspace is rendered outside Mashboard it is rendered without Ext-js, hence the slightly different look to the header. 

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

If its complicated to use the Workspace App with the options i am looking for , then i will stick with the initial app itself , could you please let me know if i copied the code in the right place?

I could still see the input parameters first , i want to see the graph first and then when i click the options buttons should be able to see the input values , here is the video http://screencast.com/t/4i2g4444jQAW

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 Not quite right, you've pasted them into the on click callback function. 

I've updated the code listing to show where they should be. Remember to clear your browser cache before viewing the app outside App Editor.

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Strange , but i lost all the earlier functionality after embedding the new code :-(

I have made sure that i cleared all the browser history,tried both FireFox and IE8

http://screencast.com/t/xCG5C87wHIk

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 What's probably happening is that the onLoad method isnt being defined until after the app initializes.

To fix this, in the App.xml file, towards the end of the document find the following line:

  <require src="js/Extension.js" type="script"/>

and change it to :

  <require loadconfirmation="Presto.BasicApp.prototype.onLoad" src="js/Extension.js" type="script"/> 

all I've done there is add the attribute loadconfirmation="Presto.BasicApp.prototype.onLoad" which will cause the app to wait until our new onLoad method has been created before initializing the App.

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

This Worked Perfect , Thank you very much !!!

I must say you have been very very helpful , Appreciate it!

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi Jeremy

I implemented the same above with another app which has additional filter values , the app works fine without the above modifications like adding .js file and changing the App.xml code as above , when i do the changes i get the error

"Failed to load app - There was an error while loading '/presto/files/system/mashlets/PendTimeDistribution_1/js/Extension.js - 20 second time out.

I have cleared the browser history ...Any advice on this please ?

Thanks

Radhika

 

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 The App has timed out waiting for the js/Extension.js load condition to be met, which in your case means Presto.BasicApp.prototype.onLoad does not exist.

You will see that error if the browser fails to parse the javascript contained in js/Extension.js. So it looks like you have a bug in your javascript. 

kishores
User offline. Last seen 1 year 4 days ago. Offline
Joined: 09/22/2008
Points: 81

 You may lint/check your JS file for errors using www.jslint.com.

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi

I just copied the previous code to the app , could not figure out why it works in some apps and why it does not in some apps,

I just recreated the app again , and i did not find that error again , but i see the input parameters appear first and then the graph , it does not work as the earlier apps ,  i am attaching all the code and a screen shot of my mashup in wires , all i did is adding couple of extra input parameters to the mashup.

4 things i needed from the code were :

1. Arrange input parameters horizontally

2.Save the input parameter values

3.Hide/Show button

4.Graph should appear first then the input parameters ,

With the current code i attached i am able to achieve all the 4 in all apps where input parameters are cluster , startdate,enddate.

Now , in the newly created mashup i have included couple of extra input parameters which are of string and date datatypes,

above 3 mentions requirements works except the 4th one....

Thanks

 

 

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

The app is actually working as expected in the app editor now , but not when opened in browser , here is the video

http://screencast.com/t/18zgWVp1ypcw

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 The only thing wrong with your code is it is missing the following lines at the end of the onLoad function :

   inputForm.hide();
   root.find('form').submit();

See attached copy of Extension.js, renamed Extension.txt

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

You should just need to clear your browser cache. 

If you make a change to an App resource file in App Editor and the App has previously been reviewed outside App Editor then any old versio of the resource file will already be cached, so you have a choice, either clear your cache or change the url of the resource by adding a url query parameter so the spec would say:

<require type='script' src='js/Extension.js?1' loadconfirmation="Presto.BasicApp.prototype.onLoad" />

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Hi Jeremy

I have posted the App to the Life Ray portal , and i dont find an options to change the input filter values , does all the work we have done for show/hide options , saving input parameter values would not be able to reflect in Life Ray ?

The user may wanted to save the input values for their requirments , Is there an option to reflect the app same as when opend in the browser?

could you please take a look at the video ...

http://screencast.com/t/tzR8XULL

 

Thank you

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

 This is the same problem we have using this App in Mashboard, we loose access to the input form toggle button, which is only rendered on the App header when viewed standalone. I'm not familiar with the Liferay container implementation, it may be possible to wire a menu option to the app to display the input form, and this would be the best solution. The best solution I can suggest is to add a simple button control to the App itself, an up/down arrow to toggle the display of the input form. 

Using App Editor, in your Extension.js file, immediately after the lines:

            inputForm.hide();
            root.find('form').submit(); 

 

append the followng code:

            // add input form display toggle
            jQuery('<div/>').
                css({ padding:'4px'}).
                attr('title','Toggle Input Form Display').
                addClass('app-form-toggle app-form-show').
                prependTo(basicAppInput);

            basicAppInput.find('.app-form-toggle').click(function(){
                inputForm.toggle();
                jQuery(this).toggleClass('app-form-show');
                jQuery(this).toggleClass('app-form-hide');
            });

Then add a new CSS resource file to the App by clicking Add and selecting CSS, call it something like Extension.css and paste in the following lines, replacing the default text "Blank Resource Created" :
 

.app-form-show {
  background: url(/prestohub/images/arrow-more.png) no-repeat scroll 0 0 transparent;
  background-position: left;
  padding-left: 10px;
  cursor:pointer;
}
.app-form-hide {
  background: url(/prestohub/images/arrow-less.png) no-repeat scroll 0 0 transparent;
  background-position: left;
  padding-left: 10px;
  cursor:pointer;
}

 

This will display an up/down arrow in the top left of the App. I've attached an updated copy of Extension.txt with this change. You can also see this code being used here:

http://prestocloud.jackbe.com/prestohub/applauncher.html?mid=Custom_Local_Search

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Thank you Jeremy , this works pretty well for the hide and show option , is there a way so that we can display the text we had in the earlier app ? like the selected input filter values ?

Basically once the app is submitted user cannot view what values are selected in the app so a display text showing the selections would be helpful and also can we change the small arrow to the gear button , or anything else which is bit bigger , a button showing "showfilters" or "hidefilter" would also be nice if it does not invlove too much coding.

 

Thank you...

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

And also , i would want the input filter to display in 3 lines ,

i have 9 input filters in my final app , and when all are arranged horizontally , user have to scroll to the far right in order to select the filters,

could you please hint me how to specify the input filters to display 3 in each line ?

Here is the code currently in the app for arranging the input filters horizontally ,

// arrange input form horizontally..
            inputs = inputForm.find('div.fieldset');
            inputForm.css({
                'position':'relative',
                'top':'0px',
                'left':'0px'
            });
            inputs.each(function(index){
                jQuery(this).css({
                    position: 'absolute',
                    top: '0',
                    left: (index * 200) + 'px'
                });
            });
            inputForm.find('button').parent().css('padding', '60px 0 0 4px');

            jQuery('<span/>').addClass('app-inputs').prependTo(headerRight);

            jQuery('<span/>').addClass('app-input-info').css({
                'font-style':'normal',
                'font-size':'13px',
                'padding-left': '20px'
            }).appendTo(headerLeft);

            jQuery('<a/>').addClass('action-app-embed app-action publish-link')
            .attr({
                'title':'Show/Hide Input Form',
                'href':'javascript:void(0);'
            }).css('background-position', '-120px 0')
            .appendTo(headerRight.find('span.app-inputs')).click(function(e){
                inputForm.toggle();
            });

            jQuery(root).find('.action-apply').click(function(){
                var inputs = '';
                inputForm.find('div.fieldset').each(function(index){
                    if(index > 0)inputs += ', ';
                    inputs += jQuery(this).find('div').first().html() + ' : ' + jQuery(this).find('.form-field').first().val();
                });
                headerLeft.find('span.app-input-info').html(inputs);
                inputForm.hide();

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

You could order the inputs into rows with 3 inputs by change the code:

            inputs.each(function(index){
                jQuery(this).css({
                    position: 'absolute',
                    top: '0',
                    left: (index * 200) + 'px'
                });
            });
            inputForm.find('button').parent().css('padding', '60px 0 0 4px');


to something like:

            var x, y;
            inputs.each(function(index){
                x = index % 3;
                y = Math.floor(index / 3);
                jQuery(this).css({
                    position: 'absolute',
                    top: (y * 60) + 'px',
                    left: (x * 200) + 'px'
                });
            });
            inputForm.find('button').parent().css('padding', (++y * 60)+'px 0 0 4px');





 

jeremy.pitten
jeremy.pitten's picture
User offline. Last seen 5 weeks 3 days ago. Offline
Joined: 09/22/2008
Points: 275

What we previously displayed in the app header could be displayed along side the form display toggle button.

In the attached file I've updated the extension.js file to include the code for arranging inputs in rows of 3, I've moved the gear icon from the app header and replaced the hide/show arrows, the title is now displayed to the right of this icon rather than on the header.

here is the code setting the title:

 

 

            setTitle = function(){
                var inputs = 'Inputs : ';
                inputForm.find('div.fieldset').each(function(index){
                    if(index > 0)inputs += ', ';
                    inputs += jQuery(this).find('div').first().html() + ' : ' + 
                           jQuery(this).find('.form-field').first().val();
                });
                basicAppInput.find('span.app-input-info').html(inputs);
            };

Also, if you are not using the up/down arrow control then the extenion.css file we added before is not needed, so that can be removed from the App. You can see this code being used here:

http://prestocloud.jackbe.com/prestohub/applauncher.html?mid=Custom_Local_Search

although it only has 3 inputs so I changed it to render 2 items per row.
 

 

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Thank you!!

newdeveloper
User offline. Last seen 41 weeks 2 days ago. Offline
Joined: 03/25/2011
Points: 120

Thank you very much!