getting requestattributes in javascript - javascript

I want to retrieve the request scope attribute in javascript as follows. How can I achieve this?
function caseChanges(req) {
var innervalue= "${dashboardTicketSummary}"
alert("nand you are 1234");
alert(innervalue);
}

Assumin the javascript is included inline on the jsp page -- you're on the right track, you just need to make sure the attribute is set (typically by your controller class) on the HttpServletRequest object, ie:
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
{
DashboardTicketSummary dts = ...; // code to obtain ticket summary here
req.setAttribute("dashboardTicketSummary", dts);
// code to dispatch to your jsp page here
}
Of course there are many other more sophisticated way -- especially is you use popular MVC framework such as Spring

set value to request attributes and write this piece of code in a script tag on jsp page (like index.jsp):
<script>
function caseChanges(req){
var innervalue= "${dashboardTicketSummary}"
alert("nand you are 1234");
alert(innervalue);
}
</script>
for better maintainability, you can gathering all attributes to a global object on jsp, and refer to it on other js files:
index.jsp
<script>
var REQUEST_ATTRS = {
dashboardTicketSummary : '${dashboardTicketSummary}',
otherAttributes :'${otherAttributes}'
};
</script>
other.js
function caseChanges(req){
var innervalue= REQUEST_ATTRS.dashboardTicketSummary ;
alert("nand you are 1234");
alert(innervalue);
}

Related

MVC Partial View Decoupling Example Code

In my Current MVC Project, I have one view with so much functionality that is has become unmanageable. In order to resolve this issue, I started added funtionality to partial views and including them in the view but even this was a problem because the underlying javascript (jquery) was so interrelated and intertwinded that it was still a mess. The JS in one partial view would call a refresh method in another partial view and created a tighly coupled disaster.
I decided I needed a way of decoupling the parital views from each other and from the container view.
Here are a few of my objects
Decouple the JS in my parital views so that one view does not need to know anything about another view or the container view.
Namespace the JS code for each view so that I do not run into nameing conflicts between views.
Create the pattern to maintian state on a page refresh (or link to this page)
Put JS into sperate files that still support razor for URL resolution and other functions with one JS file per view or partial view.
Use nameing conventions that allow someone who looks at the container view event wire up and initialization code to understand what is going on and where the refernces refer to.
Be able to pass parameter data from the trigger event to the listeners.
After doing some research and not finding to much information on this, I created a small demo that shows my first attampt at solving this issue. I am hoping that others can see what I am doing and provide even better ways of accomplishing this. In the demo, there are two partial views that communicate with each other without knowing anything about reach other. The contianing view is used to wire up the event handlers and call the functions when an event is raised.
Here is the demo code
The controler does nothing but returns the views and partial views.
PartialViewDecoupleController.cs
namespace EngA.SandboxApplication.Controllers
{
public class PartialViewDecoupleController : Controller
{
// GET: PartialViewDecouple
public ActionResult Index()
{
return View();
}
public PartialViewResult IndexJs()
{
return PartialView();
}
public PartialViewResult MenuPartialView()
{
return PartialView();
}
public PartialViewResult MenuPartialViewJs()
{
return PartialView();
}
public PartialViewResult DisplayPartialView()
{
return PartialView();
}
public PartialViewResult DisplayPartialViewJs()
{
return PartialView();
}
}
}
The index view simply loads all the views
Index.cshtml
#Html.Hidden("id")
#Html.Action("IndexJs", "PartialViewDecouple")
#Html.Action("MenuPartialView","PartialViewDecouple")
#Html.Action("MenuPartialViewJs", "PartialViewDecouple")
<br/>
<br/>
#Html.Action("DisplayPartialView", "PartialViewDecouple")
#Html.Action("DisplayPartialViewJs", "PartialViewDecouple")
The IndesJs file wires up the event handlers and marries the partail views together.
IndexJs.cshtml
<script language="javascript">
$(document).ready(function () {
//Set up Event Handlers
$(document).bind("MenuPartialView_onClick", function (e, p1) {
$("#id").val(p1);
displayPartialView.setup(p1);
});
$(document).bind("DisplayPartialView_onClick", function (e, message) {
menuPartialView.message(message);
});
//Initialize Partial Views on refresh
var id = $("#id").val();
if (id!=null) displayPartialView.setup(id);
});
</script>
Simply a container to recieve data and an button to raise an event.
DisplayPartialView.cshtml
DisplayParitalView<br/>
<div id="display">default</div>
<input type="button" name="ButtonSayHi" id="ButtonSayHi" value="Say Hi" onclick="displayPartialView.onButtonSayHiClick(this)" />
Below, "setup" displays a parameter that is passed to it.
"onButtonSayHiClick" Raises and event
DisplayPartialViewJs.cshtml
<script language="javascript">
var displayPartialView = {
setup: function (id) {
$("#display").html(id);
},
onButtonSayHiClick: function (e) {
var name = e.id;
$(document).trigger("DisplayPartialView_onClick", [name]);
}\
};
</script>
Below, Two buttens to raise events.
MenuPartialView.cshtml
MenuParitalView
<br/>
<input type="button" name="ButtonOne" value="One" onclick="menuPartialView.onButtonOneClick(this)" />
<input type="button" name="ButtonTwo" value="Two" onclick="menuPartialView.onButtonTwoClick(this)" />
Below, Triggers raise events and message displays a message that is sent to it.
MenuPartialViewJs.cshtml
<script language="javascript">
var menuPartialView = {
onButtonOneClick: function () {
$(document).trigger("MenuPartialView_onClick", [1]);
},
onButtonTwoClick: function () {
$(document).trigger("MenuPartialView_onClick", [2]);
},
message: function (message) {
alert("Message: " + message);
}
};
</script>
please let me know if you see better ways of accomplishing the same thing
Thank you
Earl
Firstly, adding scripts directly into the HTML is not a very good idea - put them in separate js files and bundle/minify then. This will save on page load times and make it easier to maintain.
A good approach is to separate your HTML by 'views' - Basically, wrap each of your views in a div with a ID e.g.
<div id="my-app-view-1">VIEW HTML</div>
By doing this, you can then scope your java script like this:
my-app-view-1.js:
(function(global) {
'use strict';
var document = global.document,
$ = global.$;
$(function() {
var $view = $(document).find('#my-app-view-1');
// do processing here
});
}(this));
This will ensure that you have modular js, and also that other scripts wont interfere with this view.

Primefaces javascript defer parsing

Primefaces 4.0 is generating lots of overhead during page loading as seen from PageSpeed Insights:
**605.3KiB of JavaScript is parsed during initial page load. Defer parsing JavaScript to reduce blocking of page rendering.**
http://localhost:8888/.../primefaces.js.xhtml?... (219.5KiB)
http://localhost:8888/.../jquery-plugins.js.xhtml?... (191.8KiB)
http://localhost:8888/.../jquery.js.xhtml?... (95.3KiB)
http://localhost:8888/.../tooltip.js.xhtml?... (34.5KiB)
http://localhost:8888/.../jsf.js.xhtml?... (25.4KiB)
http://localhost:8888/.../primefaces-extensions.js.xhtml?... (19.7KiB)
http://localhost:8888/.../watermark.js.xhtml?... (4.7KiB)
http://localhost:8888/.../hotkey.js.xhtml?... (1.2KiB)
Any idea how these 3rd party javascript files could be set to be in the bottom of the body section instead head or use defer/async parameters? Javascript loaders do not help in this case as these are coming from the JSF renderer. Also I tried to create a Listener for PreRenderView (Best way for JSF to defer parsing of JavaScript?) but that did not work out. Any other options that could solve this problem? Thanks for your help!
I got the moving of the scripts to work with the followind snippet:
public class ScriptValidateListener implements SystemEventListener {
#Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
UIViewRoot root = (UIViewRoot) event.getSource();
FacesContext ctx = FacesContext.getCurrentInstance();
List<UIComponent> resources = root.getComponentResources(ctx, "HEAD");
for (UIComponent r : resources) {
String name = (String) r.getAttributes().get("name");
if (name == null) {
continue;
}
if (name.contains(".js")) {
root.removeComponentResource(ctx, r, "HEAD");
root.addComponentResource(ctx, r, "BODY");
}
}
}
#Override
public boolean isListenerForSource(Object source) {
return (source instanceof UIViewRoot);
}
}
This moves all javascripts from HEAD to end of the BODY. But. There is this problem with Primefaces that the components rendered will try to access either JQuery ($.) or PrimeFaces javascript functions and that will break all ajax functionality on the page. Propably I will need to decide what of the scripts to move and what not to move. Also a part from the Listener I needed to define the following to faces-config.xml to make it work:
<application>
<system-event-listener>
<system-event-listener-class>com.example.listener.ScriptValidateListener</system-event-listener-class>
<system-event-class>javax.faces.event.PreRenderViewEvent</system-event-class>
</system-event-listener>
</application>

Conditionally invoking JavaScript from a bean

How do I conditionally invoke JavaScript from a bean in JSF 2?
I have a class that uses PrimeFaces which uploads user files to a particular folder, but if the user attempts to upload a file with the same name as one that is already present, I want JavaScript in this case to open up a box on the screen asking the user if he wants to overwrite the old file, or cancel the operation. If no file with that name is present, then JavaScript is not called.
I know how to test that a folder has a particular file in it, it is just that I need to know how to invoke JavaScript conditionally.
I would most appreciate any advice on this.
I have looked at variopus resources online, but still cannot get the application to work correctly. basically, this is what I have done, in an included xhtml page I have the following code for the file upload:
<p:fileUpload id="fileUpload" fileUploadListener="#{filters.upload}"
allowTypes="#{filters.uploadTypes}" invalidFileMessage="#{filters.uploadBadType}"
sizeLimit="#{filters.uploadSize}" invalidSizeMessag="#{filters.uploadBadSize}"
update="fileUpload fileTable uploadMessage" description="Select Text File"
disabled="#{filters.disableFileUploadButton}"/>
<!--- Then further in the same file is this: -->
<p:remoteCommand name="remoteCommandOverwrite" actionListender="#{filters.execOverwrite}"/>
The parent xhtml page that includes the above I have the foolowing JavaScript:
<script type="text/javascript">
function popupConfirm() {
var overwrite = confirm('Warning: This will overwrite the existing file - Do you confirm this?');
if (overwrite) remoteCommandOverwrite([{name: overwrite, value: true}]);
}
</script>
In my bean I have the following code in three methods:
public void upload(FileUploadEvent event) {
FacesMessage msg = new FacesMessage("Success! ", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
overwrite = false;
// Do what you want with the file
try {
copyFile(event.getFile().getFileName(), event.getFile().getInputstream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void copyFile(String fileName, InputStream in) {
// Initialization etc.
File file = new File(uploadFull + fileName);
if (file.exists()) {
RequestContext.getCurrentInstance().execute("popupConfirm()");
// Then test to see if overwrite is true or false, and act accordingly
}
// Then I am supposed to get the value of overwrite here:
public void execOverwrite() {
System.out.println("### execOverwrite() ###");
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> map = context.getExternalContext().getRequestParameterMap();
String soverwrite = (String) map.get("overwrite");
if (soverwrite.equals("true")) {
overwrite = true;
System.out.println("overwrite: true");
}
}
What I am trying to do is first to invoke conditionally the JavaScript function popupConfirm(). On clicking the "Upload" button that is invoked if the codition is true, which is what I want. This is then supposed to call
That works and brings up the confirm() box, but the is never called, so the method execOverwrite() in my bean is also never called, and I cannot pick up the return value and pass it to the code inside the method copyFile(). What is going wrong?
I put this problem on the back burner for about a week, and have just got back to it. I got it to work, and can pass a value back to the bean, but somehow I need to resume execution from the place where JavaScript is called.
To sumarize, my JavaScript contains the following code:
<script type="text/javascript">
function popupConfirm() {
var overwrite = confirm('Warning: This will overwrite the existing file - Do you confirm this?');
if (overwrite) remoteCommandOverwrite([{name: 'overwrite', value: 'true'}]);
}
</script>
And in the xhtml code I have:
<p:fileUpload id="fileUpload" fileUploadListener="#{filters.upload}" ...../>
<!-- Other code -->
<p:remoteCommand name="remoteCommandOverwrite" actionListener="#{filters.execOverwrite}"/>
Then on clicking the file upload button after clicking the choose file button, the code in the JavaScript, as listed above, is executed:
RequestContext.getCurrentInstance().execute("popupConfirm()");
Then on clicking "OK" in the dialog box, this method in the same bean is called:
public void execOverwrite() {
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> map = context.getExternalContext().getRequestParameterMap();
String soverwrite = map.get("overwrite");
if (soverwrite.equals("true")) {
overwrite = true; }
}
}
where the flag "overwrite" will eventually be tested to see if it is true.
Using various print statements I check that this works. However, the code does not resume executing after encountering the statement: RequestContext.getCurrentInstance().execute("popupConfirm()"); regardless of whether I enter "OK" or "Cancel" in the dialog, which is what i want it to do. It looks as if a callback of some type is required, and would most appreciate some ideas.
According to your tag, you are using PrimeFaces, so there is an easy way to invoke a javascript function from a server side event managed bean method when the browser has completed processing the server response. PrimeFaces gives you a utility class called RequestContext.
public void doActionListenerMethod() {
if (!isValid()) {
RequestContext.getCurrentInstance().execute("MyJSObject.doClientSideStuff()");
}
}
The following will execute the string argument as a Javascript when JSF has finished rendering on the client.

How to handle Javascript events via WebBrowser control for WinForms

I have read WebBrowser Control from .Net — How to Inject Javascript, Is it possible to call Javascript method from C# winforms and many others. Those examples were returns function value or alert window (synchronous calls). I have to get result from event handler (async call):
<script type="text/javascript">
window.onload = function() {
var o = new M.Build(document.getElementById("ZID"));
M.Events.observe(o, o.Events.Success, function() {
// I have to get some value!!
});
M.Events.observe(o, o.Events.Fault, function() {
// I have to get some value!!
});
}
</script>
Calling C# from JavaScript
Simply put, you can expose a C# object
to the WebBrowser that the JavaScript
can call directly The WebBrowser
class exposes a property called
ObjectForScripting that can be set by
your application and becomes the
window.external object within
JavaScript. The object must have the
ComVisibleAttribute set true
C#:
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptInterface
{
public void callMe()
{
… // Do something interesting
}
}
webBrowser1.ObjectForScripting = new ScriptInterface();
Javascript:
window.external.callMe();
Calling JavaScript in a WebBrowser control from C#
This is code I have. In the DocumentCompleted event ('cause I'm getting a page from online)
var wb = (WebBrowser)sender
//Lots of other stuff
object obj = wb.Document.InvokeScript("MyFunctionName");
Create a function that returns whatever value you need and invoke away.
You can also inject a script into the page
string js = "function MyFunctionName(){alert('Yea!');}";
HtmlElement el = wb.Document.CreateElement("script");
IHTMLScriptElement element2 = (IHTMLScriptElement)el.DomElement;
element2.text = js;
head.AppendChild(el);
which can then be invoked. That's what I've done.
If your webBrowser control is in a form, you can do the following:
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class Form1
{
public Form1()
{
InitializeComponent();
webBrowser1.ObjectForScripting = this;
}
public void CallMe()
{
//.... this method can be called in javascript via window.external.CallMe();
}
}

updating javascript in the body tag using zend framework

Hi not sure if this is possible or not but I want to programaticaly update the <body> tags to change the onload function in my zend framework application.
The App is using layouts so the body tag currently looks like this <body class="trandra">
However in one of my views I have a map from google being loaded and it needs the following in the body tag this particular view <body onload="initialize()" onunload="GUnload()">
As you can understand I don't want this to be hardcoded in my layout as this will cause all matter of nightmares with the different views.
How can this be done programaticaly, if at all it is possible? Im using the headScript functions to add the javascript so is there an equivalant for the body tag?
Thanks in advance...
Approach one - Use a layout variable
One idea would be the following:
<body class="trandra" <?php echo $this->layout()->bodyScripts ?>>
And in your view:
<?php
$this->layout->bodyScripts =
'onload="initialize()" onunload="GUnload()"';
Approach two - Additional JS-file that adds event handlers
Another approach, which is less obtrusive and doesn't affect the HTML whatsoever is to add an additional JS-file in the view that requires the onload- and onunload-handlers. It could look something like this:
<?php
$this->headScript()->appendScript(
'/path/to/javascripts/loadGMaps.js');
In your loadGMaps.js (using prototype)
Event.observe(window, 'load', function onLoadHandler() {
// Code for initializing Google maps here
});
Event.observe(window, 'unload', function onUnloadHandler() {
// Code for unloading Google maps here
});
Instead of putting your Javascript directly in the code, you could also use an non-obstrusive approch : plugging in the javascript when the page is fully loaded.
Have a look, for instance, at a function called addOnLoadEvent (can be found on many websites ^^ )
If you are using a JS Framework, it certainly has that kind of feature :
for jQuery : http://docs.jquery.com/Events/ready#fn
for prototype : http://www.prototypejs.org/api/event/observe
If you register the "plugging-in" with headScript, there should be no need to modify the tag directly.
Developed something like this recently, I've blogged about it here: http://www.evilprofessor.co.uk/311-zend-framework-body-tag-view-helper/
Demo on site and code is available via github.
I'm no expert on the Zend framework, so I don't know if there is any build in functions for this, but you could do something like this:
In layout-file:
body_params?>>
And then in your controller, you set or add to the body_params:
$this->view->body_params='onload="initialize()" onunload="GUnload()"';
I know this is an old thread, but I was looking through some of the suggested solutions and came up with one of my own playing off of some of the ideas I had seen. What I did was I extended Zend_View in my own library files (I'm using a vanilla MVC layout but similar things can be done using a bootstrap.php rather than the Bootstrap class described below)
class Custom_View extends Zend_View
{
protected $bodyAttrs = array();
public function _setBodyAttr($attrName,$attrValue=null) {
$attrName = strtolower(strval($attrName));
if(!(in_array($attrName, HTML::getValidBodyAttrs()))) {
throw new Zend_Exception(__METHOD__." attrName '$attrName' is not a valid BODY attribute!");
}
$this->bodyAttrs[$attrName] = strval($attrValue);
}
public function _getBodyAttrsAsString() {
$bodyAttrs = "";
if(count($this->bodyAttrs) > 0) {
$attrs = array();
foreach($this->bodyAttrs as $_k => $_v) {
array_push($attrs,sprintf("%s=\"%s\"", $_k, $_v));
}
$bodyAttrs = " " . implode(" ", $tags);
}
return $bodyAttrs;
}
}
// some useful tag definitions for HTML
class HTML
{
// HTML attributes as described by W3C
public static $BODY_ATTRIBUTES = array('alink','background','bgcolor','link','text','vlink');
public static $GLOBAL_ATTRIBUTES = array('accesskey','class','contenteditable','contextmenu','dir','draggable','dropzone','hidden','id','lang','spellcheck','style','tabindex','title');
public static $WINDOW_EVENT_ATTRIBUTES = array('onafterprint','onbeforeprint','onbeforeunload','onerror','onhaschange','onload','onmessage','onoffline','ononline','onpagehide','onpageshow','onpopstate','onredo','onresize','onstorage','onundo','onunload');
public static $MOUSE_EVENT_ATTRIBUTES = array('onclick','ondblclick','ondrag','ondragend','ondragenter','ondragleave','ondragover','ondragstart','ondrop','onmousedown','onmousemove','onmouseout','onmouseover','onmouseup','onmousewheel','onscroll');
public static $KEYBOARD_EVENT_ATTRIBUTES = array('onkeydown','onkeypress','onkeyup');
public static $FORM_EVENT_ATTRIBUTES = array('onblur','onchange','oncontextmenu','onfocus','onformchange','onforminput','oninput','oninvalid','onreset','onselect','onsubmit');
public static $MEDIA_EVENT_ATTRIBUTES = array('onabort','oncanplay','oncanplaythrough','ondurationchange','onemptied','onended','onerror','onloadeddata','onloadedmetadata','onloadstart','onpause','onplay','onplaying','onprogress','onratechange','onreadystatechange','onseeked','onseeking','onstalled','onsuspend','ontimeupdate','onvolumechange','onwaiting');
public static function getValidBodyAttrs() {
return array_merge(self::$BODY_ATTRIBUTES,self::$GLOBAL_ATTRIBUTES,self::$WINDOW_EVENT_ATTRIBUTES,self::$MOUSE_EVENT_ATTRIBUTES,self::$KEYBOARD_EVENT_ATTRIBUTES);
}
}
after creating this file I added a method _initView to the Bootstrap.php file pointed to by the index.php and application.ini at the root of the application directory:
protected function _initView()
{
// Custom_View extends Zend_View
$view = new Custom_View();
// Add it to the ViewRenderer
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' );
$viewRenderer->setView($view);
return $view;
}
The new, extended Zend_View now allows adding your body tags along with some simple checking for validity. Modify your layout's body tag to get the attributes:
<body<?= $this->_getBodyAttrs(); ?>>
Once you have this set up you can add your body tags to any given view
in the controller with
$this->view->_setBodyAttr('key','val');
or in the view with
$this->_setBodyAttr('key','val');

Categories