Javascript to build mvc actionlink conditionally - javascript

This is in a VB.NET MVC 3 Razor view and fires when a JsonResult of success is returned. The problem is that I would like to conditionally build an actionlink if data.Object.Status == 'Completed';
I have looked around and nothing seems to be fitting at all to solve this. This is what the actionlink should look like in razor:
#Html.ActionLink("Completed(Print Cert)", "Ind_Cert", "Printing", New With {.firstName = currentItem.firstName, .lastname = currentItem.lastName, .classRef = currentItem.course_ref, .cNumber = currentItem.conf_number}, Nothing)
And this is the javascript function that will do it. Currently it just Places the contents of data.Object.Status. Which should only show like that when data.Object.Status != 'Completed';
function updateSuccess(data) {
if (data.Success == true) {
//we update the table's info
var parent = linkObj.closest("tr");
parent.find(".CompletedClass").html(data.Object.Status);
//now we can close the dialog
$('#updateDialog').dialog('close');
//twitter type notification
$('#commonMessage').html("Update Complete");
$('#commonMessage').delay(400).slideDown(400).delay(3000).slideUp(400);
}
else {
$("#update-message").html(data.ErrorMessage);
$("#update-message").show();
}
}
Below is what I am thinking will work I am still trying to figure it out but this is a rough markup of it.
function updateSuccess(data) {
if (data.Success == true) {
//we update the table's info
var parent = linkObj.closest("tr");
var d = parent.find(".CompletedClass");
if (data.Object.Status == 'Completed') {
d.html = #Html.ActionLink("Completed(Print Cert)", "Ind_Cert", "Printing", New With {.firstName = Model(0).firstName, .lastname = Model(0).lastName, .classRef = Model(0).Completed_Class, .cNumber = Model(0).conf_number}, Nothing)
}
//now we can close the dialog
$('#updateDialog').dialog('close');
//twitter type notification
$('#commonMessage').html("Update Complete");
$('#commonMessage').delay(400).slideDown(400).delay(3000).slideUp(400);
}
else {
$("#update-message").html(data.ErrorMessage);
$("#update-message").show();
}
}

What you suggest right now should work, there is a typo on your code assigning the HTML, you probably know it but the way you add HTML to an element is (You have a = sign which is not valid) :
d.html (#Html.ActionLink("Completed(Print Cert)", "Ind_Cert", ....)
Assuming is an element that accepts html, otherwise, use the "text" function.
In any case, my recommendation would be to generate the HTML before hand but have it hidden on the page (unless you have thousands of them, of there are security concerns). Then you just have your Javascript simply show the element:
var parent = linkObj.closest("tr");
var linkElement = parent.find(".mylinkelement-class");
if (data.Object.Status == 'Completed') {
linkElement.show();
}
This should give you the benefit of allowing better separation between your Javascript and your MVC code.
HTH,
-Covo

You should update your code to something like this
d.html('#Html.ActionLink("Completed(Print Cert)", "Ind_Cert", "Printing", New With {.firstName = Model(0).firstName, .lastname = Model(0).lastName, .classRef = Model(0).Completed_Class, .cNumber = Model(0).conf_number}, Nothing)');
To assign html with jQuery you should use jQuery.html().
The Razor #Html.ActionLink will print HTML to the page, to not break your Javascript, put those inside quotes d.html('#Html...')

Related

How can the View screen be hidden from the Jquery Selector search?

I have a problem with overlapping HTML id. The reason for this problem is that more than 100 screens are opened and used one at a time, and then they are turned into multi-tabs in an active state.
I was instructed not to modify the existing code as much as possible while implementing multi-tab. Many screens are similar, so many are copied and used. Therefore, there is a case where the HTML id, which is the problem I mentioned, is duplicated.
How can I implement multi-tap with no conflicts of id without modifying existing sources as much as possible?
I thought of a way. Copy the screen and put it in the data, and then create the screen again.
The problem is that I use js-based Web Grid, but when I call the screen again, the screen is not visible. I think it's not a web grid problem. The button function that gives an alert when clicked initially works, but it did not work when it was reloaded.
HTML (Frame)
<div id="flex_navi_btn_area"></div>
<div id="menuContent"></div>
Script (Jquery Use)
function menuCall(url, inner_url_yn, obj){
let $navBtnWrap = $('.navButton.tab-content-'+obj.key);
if ($navBtnWrap.length > 0) {
$navBtnWrap.eq(0).click();
return;
} // Tab already exists
let currentKey = $('#menuContent').data('key');
if(currentKey != null && typeof currentKey != "undefined") {
$('#flex_navi_btn_area').data('content-'+currentKey, $('#menuContent').clone());
} // Save screen is use
var params = '';
ajaxCall(url, params, function(data){
$('#menuContent').empty();
$('#menuContent').append(data);
$('#menuContent').data('key', obj.key);
addTab(url, obj);
});
}
function addTab(url, obj) {
$('#flex_navi_btn_area .navButton').removeClass('on'); // For css
$('#flex_navi_btn_area').append(`<div onclick="selectTab($(this))" data-key="`+obj.key+`" class="navButton on tab-content-`+obj.key+`">`+obj.title+`</div>`); // Tab html
}
function selectTab($selectedTab) {
let currentKey = $('#menuContent').data('key');
let nextKey = $selectedTab.data('key');
if(currentKey != null && typeof currentKey != "undefined") {
$('#flex_navi_btn_area').data('content-'+currentKey, $('#menuContent').clone());
} // Save screen in use
if(currentKey == nextKey) return; // New and existing screen is same
$('#menuContent').empty();
let $content = $('#flex_navi_btn_area').data('content-'+nextKey);
if ($content != null && typeof $content != "undefined") {
$content.replaceAll($('#menuContent'));
$content.data('key', nextKey);
} // Change screen
$('#flex_navi_btn_area .navButton').removeClass('on'); // For css
$selectedTab.addClass('on'); // For css
}
HTML (content)
<div onclick="alert('html')"><div>
<div id="btn"></div>
<script>
$('#btn').click( () => { alert('js'); });
</script>
First load, working well
Second or more load, only 'html' alert working
I know that when there is the same html id, it is indistinguishable. So what I want is to isolate the screen that's currently being shown so that it can't be searched, and then bring up the screen that's been isolated and show it on the screen.
I would suggest you try something like this
My other suggestions would be, that you get make two separate arrays. One for all the buttons with a duplicate ids and one array for all the tabs with duplicate ids.
Then use a basic for loop (let i = 0; i < duplicate_btns.length; i++) find matching pairs and add i (number) to the end of the id.
Hope this helps

AJAX based search returning page information

I found the source of the error but do not know how to fix it. I'm using codeigniter and I'm trying to make a textbox with search results showing under it to help the user find what they are looking for. Think similar to google's search. When I make the AJAX call, it's returning everything on the webpage as well as the search results.
Example of issue: https://gyazo.com/244ae8f3835233a2690512cebd65876d
That textbox within the div should not be there as well as the white space. Using inspect element I realized the white spaces are my links to my CSS and JS pages. Then there's the textbox which is from my view.
I believe the issue lies within my JS.
//Gets the browser specific XmlHttpRequest Object
function getXmlHttpRequestObject() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Your Browser Sucks!\nIt's about time to upgrade don't you think?");
}
}
//Our XmlHttpRequest object to get the auto suggest
var searchReq = getXmlHttpRequestObject();
//Called from keyup on the search textbox.
//Starts the AJAX request.
function searchSuggest() {
if (searchReq.readyState == 4 || searchReq.readyState == 0) {
var str = encodeURI(document.getElementById('txtSearch').value);
searchReq.open("GET", '?search=' + str, true);
searchReq.onreadystatechange = handleSearchSuggest;
searchReq.send(null);
}
}
//Mouse over function
function suggestOver(div_value) {
div_value.className = 'suggest_link_over';
}
//Mouse out function
function suggestOut(div_value) {
div_value.className = 'suggest_link';
}
//Click function
function setSearch(value) {
document.getElementById('txtSearch').value = value;
document.getElementById('search_suggest').innerHTML = '';
}
//Called when the AJAX response is returned.
function handleSearchSuggest() {
if (searchReq.readyState == 4) {
var ss = document.getElementById('search_suggest');
ss.innerHTML = '';
var str = searchReq.responseText.split("\n");
for (i = 0; i < str.length - 1; i++) {
var suggest = '<div onmouseover="javascript:suggestOver(this);" ';
suggest += 'onmouseout="javascript:suggestOut(this);" ';
suggest += 'onclick="javascript:setSearch(this.innerHTML);" ';
suggest += 'class="suggest_link">' + str[i] + '</div>';
ss.innerHTML += suggest;
}
}
}
More specifically the getXmlHttpRequestObject function. it is returning the entire page including my header and footer. I don't believe any more info is needed but if anyone feels that way, I'll supply the view and controller.
https://gyazo.com/d0c43326191a4b09cc4b1d85d67a1bf6
This image shows the console and how the response and response text are the entire page instead of just the results.
Your call to the view method is loading the header view, the suggest view and the footer view while your suggest model is echoing the data that you're after.
You could just remove the line $this->view("suggest"); and your suggestions will be echoed.
This isn't great though. I would pass the titles back to the controller from the model then create a new controller method that outputs the data in a structured way (probably JSON).

How to populate jqGrid filter toolbar and search when the page loads (ASP.net webforms)

Currently, I'm trying to populate the filterToolbar with values taken in from a cookie. If there is cookie data for the filters, I want it to fill the respective textboxes and filter the jqGrid for that data.
I'm using ASP.net webforms, so most of my data is initialized already. How/where could I add javascript in order to get this going?
I actually figured out what I was doing.
So what I ended up doing as a solution was adding a timeout function in the document.ready function
$(document).ready(function () {
// some code
setTimeout(function () {
$('#Jqgrid1')[0].triggerToolbar();
}, 500)
//some code
}
My guess is that I couldn't use the $('#grid')[0].toggleToolbar() to force it because whenever I tried to use it, it was before the whole grid was finish setting up.
In the ASP webform, I had several functions registered.
<cc1:JQGrid ID="Jqgrid1" runat="server"
Height="630"
SearchDialogSettings-Draggable="true"
EnableViewState="false"
AutoWidth="True" >
<ClientSideEvents
LoadComplete="Jqgrid1_LoadComplete"
GridInitialized="initGrid"
/>
<%-- grid code --%>
</cc1:JQGrid>
The LoadComplete is executed after the grid is loaded. I tried doing triggering my toolbar there, but didn't work. My guess is, again, it was too early in the grid execution to use the triggerToolbar() function.
The same went for the GridInitialized events (even though both events would seem to imply to me that the grid is done doing its thing... but whatever...)
The way that I read my cookies in was actually in the GridInitialized event handler.
function initGrid() {
var myJqGrid = $(this);
var valueName = 'GridFilters';
var myCookie = document.cookie;
var gridFilterString;
var gridFilterArray;
var currentFilter;
var myCookie_arr;
var myDic = {};
if (myCookie.indexOf(valueName) > -1) { // don't even bother if the cookie isn't there...
myCookie_arr = myCookie.split("; "); // looking for the cookie I need
// read cookies into an array
for (var i = 0; i < myCookie_arr.length; i++)
{
parts = myCookie_arr[i].split("=");
first = parts.shift(); // remove cookie name
myDic[first.trim()] = parts.join("=").trim(); // handles multiple equality expressions in one cookie
}
if (myDic.hasOwnProperty("GridFilters"))
gridFilterString = myDic["GridFilters"];
if (gridFilterString != "NONE") {
myFiltersDic = {}
myFiltersArr = gridFilterString.split("&")
for (var i = 0; i < myFiltersArr.length; i++) {
parts = myFiltersArr[i].split("=");
myFiltersDic[parts[0].trim()] = parts[1].trim();
}
myParams = $(this).jqGrid("getGridParam", "postData");
var filters = []
for (keys in myFiltersDic) {
$('#gs_' + keys.trim()).val(myFiltersDic[keys].trim());
}
$.cookie('m_blnSearchIsHidden', "0", "/");
if (!isLoaded)
{
$(this)[0].toggleToolbar();
}
isLoaded = true;
}
}
}

I need to set display: block on div then find an anchor within that div

I'm nearly finished with this project but I have been beating my head against this problem for a day or so.
Big picture:
Im trying to create a link that will jump between tabs and find an anchor.
Details:
I need to create a link which triggers the function that hides the current div (using display: none)/shows another div (display: block;) and then goto an anchor on the page.
My first intuition was to do:
code:
<a onClick="return toggleTab(6,6);" href="#{anchor_tab_link_name}">{anchor_tab_link_name}</a>
Since the onClick should return true and then execute the anchor. However it loads but never goes to the anchor.
Here is the toggleTab function to give some context:
function toggleTab(num,numelems, anchor, opennum,animate) {
if ($('tabContent'+num).style.display == 'none'){
for (var i=1;i<=numelems;i++){
if ((opennum == null) || (opennum != i)){
var temph = 'tabHeader'+i;
var h = $(temph);
if (!h){
var h = $('tabHeaderActive');
h.id = temph;
}
var tempc = 'tabContent'+i;
var c = $(tempc);
if(c.style.display != 'none'){
if (animate || typeof animate == 'undefined')
Effect.toggle(tempc,'appear',{duration:0.4, queue:{scope:'menus', limit: 3}});
else
toggleDisp(tempc);
}
}
}
var h = $('tabHeader'+num);
if (h)
h.id = 'tabHeaderActive';
h.blur();
var c = $('tabContent'+num);
c.style.marginTop = '2px';
if (animate || typeof animate == 'undefined'){
Effect.toggle('tabContent'+num,'appear',{duration:0.4, queue:{scope:'menus', position:'end', limit: 3}});
}else{
toggleDisp('tabContent'+num);
}
}
}
So I posted this on a coding forum and a person told me that my tab code was done in prototype.
And that I should "Long story short: don't use onclick. Attach the data to the A tag and handle the click event yourself (using preventDefault() or similar) to do your tab-setting stuff, then when it's done, manually set your location to the hash tag."
I do understand what he is suggesting but I don't know how to implement it because I don't know much about javascript syntax.
If you can provide any hints or suggestions it would be amazing.
Update:
I tried to implement the solution below like this:
The link:
<a id="trap">trap</a>
Then adding the following js to the top of the page:
<script type="javascript">
document.getElementById("trap").click(function() { // bind click event to link
tabToggle(6,6);
var anchor = $(this).attr('href');
//setTimeout(infoSupport.gotoAnchor,600, anchor);
jumpToAnchor();
return false;
});
//Simple jump to anchor point
function jumpToAnchor(){
location.href = location.href+"#trap";
}
//Nice little jQuery scroll to id of any element
function scollToId(id){
window.scrollTo(0,$("#"+id).offset().top);
}
</script>
But unfortunately it simply doesn't seem to work for me. When I click the text simply nothing happens.
Anyone notice any apparent mistakes? I'm not used of working with javascript.
I found a lot simpler solution:
$(function(){
jumpToTarget('spot_to_go'); //This is what you put inside your function when the link is clicked.
function jumpToTarget(target){
var target_offset = $("#"+target).offset();
var target_top = target_offset.top;
$('html, body').animate({scrollTop:target_top}, 500);
}
});
Working demo:
http://jsbin.com/ivure/3/edit
So on the click event you do something like this:
//Untested
$('#trap').click(function(){
tabToggle(6,6);
var anchor = $(this).attr('href');
jumpToTarget(anchor);
return false;
});
​
Apparently a small delay was all I needed.
I used this for the link. This is preferred for my situation since I'm batch generating many of these links.
trap
Then I used this vanilla javascript
//Simple jump to anchor point
function jumpToAnchor(target){
setTimeout("window.location.hash=target",450);
}
This loads the link and instantly goes to the location. No jerkiness or anything.

How to prevent iframe load event?

I have an iframe and couple of tables on my aspx page. Now when the page loads these tables are hidden. The iframe is used to upload file to database. Depending on the result of the event I have to show a particular table on my main page (these tables basically have "Retry","next" buttons...depending on whether or not the file is uploaded I have to show respective button).
Now I have a JavaScript on the "onload" event of the iframe where I am hiding these tables to start with. When the control comes back after the event I show a particular table. But then the iframe loads again and the tables are hidden. Can any one help me with this problem. I don't want the iframe to load the second time.
Thanks
mmm you said you're on aspx page,
I suppose that the iframe do a postback, so for this it reload the page.
If you can't avoid the postback, you've to set a flag on the main page just before posting back, and check against that while you're loading...
...something like:
mainpage.waitTillPostBack = true
YourFunctionCausingPostBack();
..
onload=function(){
if(!mainpage.waitTillPostBack){
hideTables();
}
mainpage.waitTillPostBack = false;
}
I am not sure what your problem is, but perhaps your approach should be a little different. Try putting code into the iframe what would call functions of the parent. These functions would display the proper table:
<!-- in the main page --->
function showTable1() {}
<!-- in the iframe -->
window.onload = function () {
parent.showTable1();
}
This would put a lot of control into your iframe, away from the main page.
I don't have enough specifics from your question to determine if the iframe second load can be prevented. But I would suggest using a javascript variable to check if the iframe is being loaded a second time and in that case skip the logic for hiding the tables,
This is my code
function initUpload()
{
//alert("IFrame loads");
_divFrame = document.getElementById('divFrame');
_divUploadMessage = document.getElementById('divUploadMessage');
_divUploadProgress = document.getElementById('divUploadProgress');
_ifrFile = document.getElementById('ifrFile');
_tbRetry = document.getElementById('tbRetry');
_tbNext=document.getElementById('tblNext');
_tbRetry.style.display='none';
_tbNext.style.display='none';
var btnUpload = _ifrFile.contentWindow.document.getElementById('btnUpload');
btnUpload.onclick = function(event)
{
var myFile = _ifrFile.contentWindow.document.getElementById('myFile');
//Baisic validation
_divUploadMessage.style.display = 'none';
if (myFile.value.length == 0)
{
_divUploadMessage.innerHTML = '<span style=\"color:#ff0000\">Please select a file.</span>';
_divUploadMessage.style.display = '';
myFile.focus();
return;
}
var regExp = /^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.doc|.txt|.xls|.docx |.xlsx)$/;
if (!regExp.test(myFile.value)) //Somehow the expression does not work in Opera
{
_divUploadMessage.innerHTML = '<span style=\"color:#ff0000\">Invalid file type. Only supports doc, txt, xls.</span>';
_divUploadMessage.style.display = '';
myFile.focus();
return;
}
_ifrFile.contentWindow.document.getElementById('Upload').submit();
_divFrame.style.display = 'none';
}
}
function UploadComplete(message, isError)
{
alert(message);
//alert(isError);
clearUploadProgress();
if (_UploadProgressTimer)
{
clearTimeout(_UploadProgressTimer);
}
_divUploadProgress.style.display = 'none';
_divUploadMessage.style.display = 'none';
_divFrame.style.display = 'none';
_tbNext.style.display='';
if (message.length)
{
var color = (isError) ? '#008000' : '#ff0000';
_divUploadMessage.innerHTML = '<span style=\"color:' + color + '\;font-weight:bold">' + message + '</span>';
_divUploadMessage.style.display = '';
_tbNext.style.display='';
_tbRetry.style.display='none';
}
}
tblRetry and tblNext are the tables that I want to display depending on the result of the event.

Categories

Resources