DNN 7 Open a page/module in a modale - dotnetnuke

Working on DNN 7 , I have a grid where I display somes users infos.
I would like to set an "edit action", to edit the user, like into admin panel.
So I choose to make a modale into the same page.
<rad:GridTemplateColumn HeaderStyle-Width="0" ItemStyle-HorizontalAlign="Center" AllowFiltering="False">
<ItemTemplate>
<a href="#" data-id="<%#((CustomerViewModel)Container.DataItem).UserID%>" class="e">
<img src='<%=ResolveUrl("~/Icons/Sigma/Edit_16x16_Standard.png")%>' title='Edit user' />
</a>
</ItemTemplate>
</rad:GridTemplateColumn>
// edit user infos
$('.e').click(function () {
var url = "<%= GetEditUrlUser() %>".replace(new RegExp("KEYFIELD", "g"), $(this).attr("data-id"));
//alert(url);
dnnModal.show(url, true, 550, 950, false, '');
return false;
});
And here my cs function
public string GetEditUrlUser()
{
// I need to show "dnndev.me/en-us/Admin/User-Accounts/ctl/Edit/mid/"+ModuleId+"/UserId/KEYFIELD/filter/All/pagesize/10/currentpage/0?popUp=true ";
var url = Globals.NavigateURL("393", "Edit", "mid=" + ModuleId, "UserID=KEYFIELD", "filter/All/pagesize/10/currentpage/0", "popUp=true");
return url;
}
But that's not good, since Globals.NavigateURL() return me the page where I am.
I have also took a look about ResolveUrl() function, but didn't succeed to do something well.
So if someone can help me, or give me an example / tips, it would be great.
Thanx
EDIT : It working with this code, but it doesn't seems optimised and really great
public string GetEditUrlUser()
{
var url = Globals.NavigateURL("Edit", "mid","393","UserID","KEYFIELD", "filter/All/pagesize/10/currentpage/0", "popUp=true");
return url;
}
EDIT 2 : To make it more efficient, I got this actually. But this isn't working, I got a blank modale.
But this way look like really better, since it will search itself for admin module
public string GetEditUrlUser()
{
// dnndev.me/en-us/Admin/User-Accounts/ctl/Edit/mid/"+ModuleId+"/UserId/KEYFIELD/filter/All/pagesize/10/currentpage/0?popUp=true
var moduleController = new ModuleController();
var adminUserModule = moduleController.GetModuleByDefinition(PortalId, "User Accounts");
var url = EditUrl(adminUserModule.TabID, "Edit", false, "mid="+adminUserModule.ModuleID, "userId=KEYFIELD");
return url;
}

Okay, I think, finally, I got it.
The ASCX code would be
<rad:GridTemplateColumn HeaderStyle-Width="0" ItemStyle-HorizontalAlign="Center" AllowFiltering="False">
<ItemTemplate>
<a href="#" data-id="<%#((CustomerViewModel)Container.DataItem).UserID%>" class="e">
<img src='<%=ResolveUrl("~/Icons/Sigma/Edit_16x16_Standard.png")%>' title='Edit user' />
</a>
</ItemTemplate>
</rad:GridTemplateColumn>
With somes Javascript Function for self-update without reload the page.
function refreshGrid() {
// grdCustomers should be the ID of your grid
$find("<%= grdCustomers.ClientID %>").get_masterTableView().rebind();
}
// edit user infos
$('.e').click(function () {
var url = "<%= GetEditUrlUser() %>".replace(new RegExp("KEYFIELD", "g"), $(this).attr("data-id"));
dnnModal.show(url,/*showReturn*/true, 550, 950, true, 'javascript:parent.window.refreshGrid()');
return false;
});
And into the CS file, it should be like.
public string GetEditUrlUser()
{
var moduleController = new ModuleController();
var adminUserModule = moduleController.GetModuleByDefinition(PortalId, "User Accounts");
var url = Globals.NavigateURL(adminUserModule.TabID, "Edit", "mid=" + adminUserModule.ModuleID, "userId=KEYFIELD", "popUp=true");
return url;
}
And it work fine.
I hope it could help someone.

Related

Protractor: Drag-Drop function working with Mozilla and chrome but not with Internet Explorer 11

I am trying to automate a drag-drop action using protractor.
The element's properties are:
Element that needs to be dragged:
<li id="activities-test123" class="ng-binding ng-scope ng-isolate-scope draggable" tooltip-placement="right" ng-attr-tooltip="{{activity.name.length > relationships.nameLimit ? activity.name : ''}}" draggable="true" ng-class="{'draggable-disabled': activity.entityHasActivity, 'draggable': !activity.entityHasActivity}" ng-repeat="activity in relationships.activities | toArray:false | filter:searchActivities:strict" tooltip="">
The location where the element needs to be dropped:
<div class="tree-view ng-isolate-scope" drop="relationships.handleDrop" datasource="relationships" droppable="">
<p class="content-help-text ng-hide" ng-hide="relationships.hasEntity()">Drag an entity here</p>
<div ui-tree="relationships.options">
<ol class="top-level ng-isolate-scope" droppable="" ui-tree-nodes="">
<!-- ngRepeat: item in relationships.tree -->
</ol>
</div>
</div>
I am using a drag-drop-helper native script which I found in GitHub
module.exports =function simulateDragDrop(sourceNode, destinationNode) {
var EVENT_TYPES = {
DRAG_END: 'dragend',
DRAG_START: 'dragstart',
DROP: 'drop'
}
function createCustomEvent(type) {
var event = new CustomEvent("CustomEvent")
event.initCustomEvent(type, true, true, null)
event.dataTransfer = {
data: {
},
setData: function(type, val) {
this.data[type] = val
},
getData: function(type) {
return this.data[type]
}
}
return event
}
function dispatchEvent(node, type, event) {
if (node.dispatchEvent) {
return node.dispatchEvent(event)
}
if (node.fireEvent) {
return node.fireEvent("on" + type, event)
}
}
var event = createCustomEvent(EVENT_TYPES.DRAG_START)
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event)
var dropEvent = createCustomEvent(EVENT_TYPES.DROP)
dropEvent.dataTransfer = event.dataTransfer
dispatchEvent(destinationNode, EVENT_TYPES.DROP, dropEvent)
var dragEndEvent = createCustomEvent(EVENT_TYPES.DRAG_END)
dragEndEvent.dataTransfer = event.dataTransfer
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_END, dragEndEvent)
}
The problem is that the drag-drop action is working in Mozilla and Chrome browsers. But giving error:
UnknownError: JavaScript error (WARNING: The server did not provide any stacktrace information) on running the browser.executeScript command in Internet Explorer 11.
I am implementing the code in following way:
var DragAndDrop = require("./../native_js_drag_and_drop_helper.js");
var input = element(by.xpath("XPATH OF ELEMENT TO BE MOVED"));
var target = element(by.xpath("XPATH OF THE TARGET LOCATION"));
browser.executeScript(DragAndDrop, input.getWebElement(), target.getWebElement());
I verified the browser.executeScript command by running browser.executeScript('javascript:localStorage.clear(); alert("HelloWorld");'); and its working fine with IE11.
Can someone give me an idea what i am missing here?
I got this error fixed.
The IE 11 browser doesn't support CustomEvent constructor in the line:var event = new CustomEvent("CustomEvent"). Change CustomEvent to createEvent. var event=document.createEvent("CustomEvent");. Works like a Charm!!

using window.open with knockout binding

I'm using knockout's foreach loop that fetches the values from an array and displays it in a href tag.
This all works well but once I use javascript's onclick (I need this onclick as I am using InAppBrowser plugin for mobiles) and uses the variables inside it, it doesn't work. See example here:
<div data-bind="foreach: consumerData" style="margin-bottom:100px;">
<table>
<tr>
<td colspan="2">
<p style="font-size:larger; margin-bottom:5px;">
<a style="text-decoration:none;"
data-bind="attr: { href: 'http://domain:8080/dsservlet/'+$data[0]+'.png?key=DK188961' },
text: $data[1]" target="_blank"
onclick="window.open('http://domain:8080/dsservlet/'+$data[0]+'.png?key=DK188961',
'_blank', 'location=yes'); return false;"></a></p>
</td></tr>
</table>
</div>
As you can see the $data[0] works fine inside the data-bind attribute. But using the same $data[0] inside the onclick doesn't work which is still inside the foreach loop. I assume I need to declare a javascript variable to be able to make it work, but how do I declare it inside the foreach loop? I need to declare it inside the foreach loop as the array varies with different values.
See the javscript part here:
var ViewModel = function() {
this.consumerData = ko.observableArray([[174302,"BUSINESS - APPLICATION TO CONDUCT A BUSINESS FROM HOME.pdf",".pdf","DK89639"],[120183,"Glovent-Brochure.pdf",".pdf","DK472894"]]);
}
ko.applyBindings(new ViewModel());
With Knockout there's a different way to handle onclick: use a click binding handler. Like this:
var ViewModel = function() {
var self = this;
this.consumerData = ko.observableArray([[174302,"BUSINESS - APPLICATION TO CONDUCT A BUSINESS FROM HOME.pdf",".pdf","DK89639"],[120183,"Glovent-Brochure.pdf",".pdf","DK472894"]]);
this.openServlet = function(data) {
window.open('http://domain:8080/dsservlet/'+data[0]+'.png?key=DK188961', '_blank', 'location=yes');
};
};
ko.applyBindings(new ViewModel());
<a data-bind="attr: { href: 'http://domain:8080/dsservlet/'+$data[0]+'.png?key=DK188961' },
click: $parent.openServlet
text: $data[1]"
target="_blank"></a>
Please read linked documentation carefully, it'll have the answers to many follow-up questions that might arise.
Finally, consider converting consumerData to a proper sub view model in its own right, instead of a raw array of data. This would allow you to create the href in an observable or computed observable, thus also allowing you to unit test it.
As a footnote, if you really need to have an onclick you could set it using the attr binding you also used for href. So for example:
var ConsumerData = function(data) {
var self = this;
self.id = data[0];
self.filename = data[1];
self.extension = data[2];
self.code = data[3];
self.url = 'http://domain:8080/dsservlet/' + self.id + '.png?key=DK188961';
self.openServlet = function() {
window.open(self.url, '_blank', 'location=yes');
};
self.onclickValue = "window.open('http://domain:8080/dsservlet/'+data[0]+'.png?key=DK188961', '_blank', 'location=yes'); return false";
// Overwrite them again for testing on StackOverflow (window.open is crap for testing)
self.openServlet = function() { alert(self.url); };
self.onclickValue = "alert('" + self.url + "'); return false;";
};
var ViewModel = function() {
this.consumers = ko.observableArray([
new ConsumerData([174302, "BUSINESS - APPLICATION TO CONDUCT A BUSINESS FROM HOME.pdf", ".pdf", "DK89639"]),
new ConsumerData([120183, "Glovent-Brochure.pdf", ".pdf", "DK472894"])
]);
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<div data-bind="foreach: consumers">
<p>
<a data-bind="attr: { href: url, onclick: onclickValue }, click: openServlet, text: filename" target="_blank"></a>
</p>
</div>

Two way binding with ng-src (angularjs)

I'm trying to display webview using angularjs and make the webview url stocken in a list of webviews : webview.url. The problem is when a person start navigate in the webview, the url change in the webview (src attribute) but not in the webvew.url in the list of items.
To understand this issue I made this example with Iframe : http://plnkr.co/edit/MTgNNNZefliS507Fw0Jj?p=preview
How can I make the src value changing in the webview modifie automatically the webview.url in my list of items ? I mean make ng-src 2-way-binding.
Thanks!
In my page:
<ul id="myviews" class="cd-nav">
<li id="{{webView.id}}" ng-repeat="webView in webViews">
<webview id="webview{{webView.id}}" class="mywebviews" ng-src="{{webView.url}}">
</webview>
</li>
</ul>
In my app.js :
var trustedUrl = $scope.trustSrc("http://google.com");
$scope.webViews = [
{
id : "webview0",
url: trustedUrl,
classe: "opened"
}
];
When a client try to visit an url:
var idnewwebview = $scope.webViews.length + 1;
var trustedUrl =.// Recupered via an input...
$scope.webViews.push(
{
id : idnewwebview,
url: trustedUrl,
classe: "opened"
}
);

Backbone.js create method not sending parameters to sinatra

I'm new to backbone and trying to set it up in Sinatra, but I can't seem to get a simple create working.
I've set up my model/collection as so:
var TEAM_ID = window.location.pathname.split('/')[1]; // From url
$(function () {
var TeamMember = Backbone.Model.extend({
defaults: {
name : ""
}
});
var TeamMembers = Backbone.Collection.extend({
model: TeamMember,
url: "/" + TEAM_ID + "/team-members.json"
});
var teamMembers = new TeamMembers;
var TeamMemberView = Backbone.View.extend({
events: {
"click #new-team-member-form .submit-button" : "handleNewTeamMember"
},
handleNewTeamMember: function(data) {
var inputField = $('input[name=new_team_member_name]');
console.log("Pre create");
// This doesn't get sent to the server!!
var teamMember = teamMembers.create({name: inputField.val());
console.log("Post create");
return false; // Don't submit form
},
render: function() {
console.log("Render team member");
return this;
}
});
// ...
var teamMemberView = new TeamMemberView({el: $('#week-view')});
});
The html looks like:
<table id="week-view">
<!-- ... -->
<form id="new-team-member-form" action="/some-add-url" method="post">
<fieldset class="new-object-fieldset" title="New team member">
<legend>New team member</legend>
<label for="new_team_member_name">Add new</label>
<input type="text" name="new_team_member_name" title="Add member" class="new-object-text-box" />
<button type="submit" name="new_team_member" value="new_team_member" class="submit-button">+</button>
<div id="help-new"></div>
</fieldset> <!-- New team member -->
</form>
<!-- ... -->
and the ruby looks like:
post '/:team_id/team-members.json' do
logger.info("Add team member (json): #{params}")
end
However, the sinatra server only shows params[:team_id], without the name parameter on the teamMembers.create line. Am I doing something stupid in backbone? Not initialising something properly?
I've looked at http://documentcloud.github.com/backbone/#Collection-create,
http://documentcloud.github.com/backbone/docs/todos.html, http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/, http://liquidmedia.ca/blog/2011/01/an-intro-to-backbone-js-part-2-controllers-and-views/ and https://gist.github.com/1655019, but I can't seem to find any answers there. I feel like I've done something stupid, but just can't see it!
It turns out, it was me not knowing how to extract json parameters in sinatra properly. From this site: http://mini.softwareas.com/posting-json-to-a-sinatra-mongodb-service, I found out I had to use request.body.read.to_s instead of the params hash ie,
post '/:team_id/team-members.json' do
request_body = JSON.parse(request.body.read.to_s)
team_member_name = request_body["name"]
# ...
end
I had the same problem. I am on PHP, though. Since Backbone sends POST data not in a query string, but rather in a plain JSON string, the data is not available thru $_POST. To read the Backbone POST data:
// the 'true' param returns an array rather than an object
$post = json_decode(file_get_contents('php://input'), true);
You can also read it directly from $HTTP_RAW_POST_DATA.

How to print ExtJS component?

How do I pop up the Print dialog that will print out a component when OK-ed?
var targetElement = Ext.getCmp('PrintablePanelId');
var myWindow = window.open('', '', 'width=200,height=100');
myWindow.document.write('<html><head>');
myWindow.document.write('<title>' + 'Title' + '</title>');
myWindow.document.write('<link rel="Stylesheet" type="text/css" href="http://dev.sencha.com/deploy/ext-4.0.1/resources/css/ext-all.css" />');
myWindow.document.write('<script type="text/javascript" src="http://dev.sencha.com/deploy/ext-4.0.1/bootstrap.js"></script>');
myWindow.document.write('</head><body>');
myWindow.document.write(targetElement.body.dom.innerHTML);
myWindow.document.write('</body></html>');
myWindow.print();
write your extjs printable component into document.
I like Gopal Saini's answer! I took his approach and wrote a function for one of my apps. Here's the code. Tested on FF and Safari. Haven't tried it on IE but it should work.
print: function(el){
var win = window.open('', '', 'width='+el.getWidth()+',height='+el.getHeight());
if (win==null){
alert("Pop-up is blocked!");
return;
}
Ext.Ajax.request({
url: window.location.href,
method: "GET",
scope: this,
success: function(response){
var html = response.responseText;
var xmlDoc;
if (window.DOMParser){
xmlDoc = new DOMParser().parseFromString(html,"text/xml");
}
else{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(html);
}
win.document.write('<html><head>');
win.document.write('<title>' + document.title + '</title>');
var xml2string = function(node) {
if (typeof(XMLSerializer) !== 'undefined') {
var serializer = new XMLSerializer();
return serializer.serializeToString(node);
} else if (node.xml) {
return node.xml;
}
}
var links = xmlDoc.getElementsByTagName("link");
for (var i=0; i<links.length; i++){
win.document.write(xml2string(links[i]));
}
win.document.write('</head><body>');
win.document.write(el.dom.innerHTML);
win.document.write('</body></html>');
win.print();
},
failure: function(response){
win.close();
}
});
}
ExtJS 4.1:
https://github.com/loiane/extjs4-ux-gridprinter
Printing in ExtJS is not paticularly easy. The best resource I've found on making components printable can be found on a Sencha architect's blog. The post describes how to set up custom print renderers for components, and other details about printing. However, this information is for ExtJS 3.x; it's possible that ExtJS 4 has made printing easier.
You can also add a component to be printed to the Ext.window.Window with a modal property set to true and just open a standard print dialog which will only print the desired component.
var view = this.getView();
var extWindow = Ext.create('Ext.window.Window', { modal: true });
extWindow.add(component); // move component from the original panel to the popup window
extWindow.show();
window.print(); // prints only the content of a modal window
// push events to the event queue to be fired on the print dialog close
setTimeout(function() {
view.add(component); // add component back to the original panel
extWindow.close();
}, 0);
Another option to consider is to render the component to an image or pdf. While the pop-up window/print option is nice, some browsers don't print correctly. They tend to ignore background images, certain css properties, etc. To get the component to print exactly the way it appears in the pop-up window, I ended up writing some server side code to transform the html into an image.
Here's what the client code looks like:
print: function(el){
var waitMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
waitMask.show();
//Parse current url to set up the host and path variables. These will be
//used to construct absolute urls to any stylesheets.
var currURL = window.location.href.toString();
var arr = currURL.split("/");
var len = 0;
for (var i=0; i<arr.length; i++){
if (i<3) len+=(arr[i].length+1);
}
var host = currURL.substring(0, len);
if (host.substring(host.length-1)=="/") host = host.substring(0, host.length-1);
var path = window.location.pathname;
if (path.lastIndexOf("/")!=path.length-1){
var filename = path.substring(path.lastIndexOf("/")+1);
if (filename.indexOf(".")!=-1){
path = path.substring(0, path.lastIndexOf("/")+1);
}
else{
path += "/";
}
}
//Start constructing an html document that we will send to the server
var html = ('<html><head>');
html += ('<title>' + document.title + '</title>');
//Insert stylesheets found in the current page. Update href attributes
//to absolute URLs as needed.
var links = document.getElementsByTagName("link");
for (var i=0; i<links.length; i++){
var attr = links[i].attributes;
if (attr.getNamedItem("rel")!=null){
var rel = attr.getNamedItem("rel").value;
var type = attr.getNamedItem("type").value;
var href = attr.getNamedItem("href").value;
if (href.toLowerCase().indexOf("http")!=0){
if (href.toString().substring(0, 1)=="/"){
href = host + href;
}
else{
href = host + path + href;
}
}
html += ('<link type="' + type + '" rel="' + rel+ '" href="' + href + '"/>');
}
}
html += ('</head><body id="print">');
html += (el.dom.innerHTML);
html += ('</body></html>');
//Execute AJAX request to convert the html into an image or pdf -
//something that will preserve styles, background images, etc.
//This, of course, requires some server-side code. In our case,
//our server is generating a png that we return to the client.
Ext.Ajax.request({
url: "/WebServices/Print?action=submit",
method: "POST",
rawData: html,
scope: this,
success: function(response){
var url = "/WebServices/Print?action=pickup&id="+response.responseText;
window.location.href = url;
waitMask.hide();
},
failure: function(response){
win.close();
waitMask.hide();
var msg = (response.responseText.length>0 ? response.responseText : response.statusText);
alert(msg);
}
});
}
Again, this requires some server-side magic to transform the html into an image. In my case, I implemented a "Print" service. Clients submit job requests via the "submit" action and retrieve output products via the "pickup" action.
To convert html to images, I ended up using a free command line app called Web Screen Capture. It only works on windows and I don't know how scalable it is so use at your risk.

Resources