(bootstrap 3)Lost focus when open second window from first - twitter-bootstrap-3

I'm using bootstrap for create modal windows in my project. When i create only one window all work fine. If i create second window from first i have a problem.
In First window when i try to scroll it all fine. Window is scrolling. When i open next window from it - scrolling not a current window. Scrolling body behind it.
Example https://jsfiddle.net/rz4p503n/5/
For create modal window I'm using such function:
function createModalWindow(windowid, parentid, template){
if (parentid.localeCompare('')!=0){
$(('#' + parentid)).modal('hide');
}
$('#' + windowid).detach();
$("body").append(template);
$('#' + windowid).modal('show');
}
When i create first window body has class 'modal-open'. It removed after create next window.
Why is this happening?
I think lost a focus for scrolling because body hasn't this class.
UPD: I tried to modify create/close window function such as:
$('body').on('click','.close-and-exit', function () {
console.log('try to close');
var windowid =$(this).closest('.modal').attr('id');
var parentid =$(this).closest('.modal').attr('data-parentid');
console.log({windowid: windowid, parentid:parentid});
$('#' + windowid).modal('hide');
$(('#' + windowid)).on('hidden.bs.modal', function (e) {
//$('#' + parentid).modal('show');
console.log('window: ' + windowid + ' is closed');
if (typeof parentid!=='undefined'){
if(parentid.localeCompare('')!=0){
console.log(' try to show parent window: ' + parentid);
$('#' + parentid).modal('show');
}
}
})
});
function createModalWindow(windowid, parentid, template){
console.log('parentid: ' + parentid);
console.log('windowid: ' + windowid);
if (parentid.localeCompare('')!=0){
$(('#' + parentid)).modal('hide');
$(('#' + parentid)).on('hidden.bs.modal', function (e) {
console.log('parent is hided. create new windowĐ–');
$('#' + windowid).detach();
$("body").append(template);
$('#' + windowid).modal('show');
})
}
else{
$('#' + windowid).detach();
$("body").append(template);
$('#' + windowid).modal('show');
}
}
Focus not losses. Scrol work only in current window. But a can not close first window after second window. Everytime running
$(('#' + parentid)).on('hidden.bs.modal', function (e) {...});
from function createModalWindow and it call
$('#' + windowid).detach();
$("body").append(template);
$('#' + windowid).modal('show');
How I can fix it? I need to scroll and close the window correctly too.

I fixed this problem using hidden.bs.modal.
For create function:
function createModalWindow(windowid, parentid, template){
if (parentid.localeCompare('')!=0){
$(('#' + parentid)).modal('hide');
$(('#' + parentid)).on('hidden.bs.modal', function (e) {
console.log('parent is hided. try to set modal class for body');
if (($('body').hasClass('modal-open')==false)&& (parentid.localeCompare('')!=0)){
$('body').addClass('modal-open');
}
})
}
$('#' + windowid).detach();
$("body").append(template);
$('#' + windowid).modal('show');
}
For close window:
$('body').on('click','.close-and-exit', function () {
console.log('try to close');
var windowid =$(this).closest('.modal').attr('id');
var parentid =$(this).closest('.modal').attr('data-parentid');
$('#' + windowid).modal('hide');
$(('#' + windowid)).on('hidden.bs.modal', function (e) {
console.log('window: ' + windowid + ' is closed');
if (($('body').hasClass('modal-open')==false)&& (parentid.localeCompare('')!=0)){
$('body').addClass('modal-open');
}
});
if (typeof parentid!=='undefined'){
if(parentid.localeCompare('')!=0){
console.log(' try to show parent window: ' + parentid);
$('#' + parentid).modal('show');
}
}
});
For undestand: when the hidden.bs.modal is triggered, I call a check body hasClass 'modal-open' and parentid is not null. Script will add class 'modal-open' to body if body hasn't this class and present parent window

Related

Titanium Alloy - 'Global' Listener

I have multiple windows that 'require' livebar so that the entire bar persists over all windows. However, whenever the 'change' function is called, it works and logs, however my $.livebar_datalbl.text fails with the following error: "undefined is not an object (evaluating '$.livebar_datalbl.text = 'State: ' + e.description + ' (' + e.state + ')'')"
Am I structuring the code incorrectly or missing something?
index.js
(function constructor() {
audioPlayer = Ti.Media.createAudioPlayer({
url: 'https://allthingsaudio.wikispaces.com/file/view/Shuffle%20for%20K.M.mp3/139190697/Shuffle%20for%20K.M.mp3',
allowBackground: true
});
audioPlayer.addEventListener('progress', function(e) {
Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
});
audioPlayer.addEventListener('change', function(e) {
$.livebar_datalbl.text = 'State: ' + e.description + ' (' + e.state + ')';
Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
});
window = Alloy.createController('listen').getView();
window.open();
})();
livebar.xml
<Alloy>
<View class="livebar">
<View class="livebar_livelblcontainer">
<Label class="livebar_livelbl">LIVE</Label>
</View>
<Label class="livebar_datalbl" id="livebar_datalbl">HELLO WORLD</Label>
<ImageView id="livebar_playpausebtn" class="livebar_playpausebtn"/>
</View>
</Alloy>
livebar.js
$.livebar_playpausebtn.addEventListener('click', function(event) {
if (audioPlayer.playing || audioPlayer.paused) {
audioPlayer.stop();
if (Ti.Platform.name === 'android')
{
audioPlayer.release();
}
} else {
audioPlayer.start();
}
});
audioPlayer.addEventListener('progress', function(e) {
Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
});
audioPlayer.addEventListener('change', function(e) {
$.livebar_datalbl.text = 'State: ' + e.description + ' (' + e.state + ')';
Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
});
The audioPlayer.addEventListener event will only listen to events in the controller that you have created the audioPlayer in, in this case index.js. In your example the audioPlayer.addEventListener events in livebar.js have no effect as there is no audioPlayer to add event to.
If you would like to have the audioplayer in index.js and then have the livebar be updated and still keep the livebar in its own view+controller you will need to fire events across the controllers. To do this you can make use of Ti.App.fireEvent
You can read more here - Search for the "Application-Level Events" Section
http://docs.appcelerator.com/platform/latest/#!/guide/Event_Handling
You could do something like below.
Remember to be careful with App wide event listeners, you should always remove
those when you are done with them via the function below
Ti.App.removeEventListener("eventlistenername", eventfunctionname);
index.js
(function constructor() {
audioPlayer = Ti.Media.createAudioPlayer({
url: 'https://allthingsaudio.wikispaces.com/file/view/Shuffle%20for%20K.M.mp3/139190697/Shuffle%20for%20K.M.mp3',
allowBackground: true
});
audioPlayer.addEventListener('progress', function(e) {
Ti.API.info('Time Played: ' + Math.round(e.progress) + ' milliseconds');
});
audioPlayer.addEventListener('change', function(e) {
// set livebareText
var livebareText = 'State: ' + e.description + ' (' + e.state + ')';
// fire app wide event
Ti.App.fireEvent("app:updateLivebar",livebareText);
Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
});
window = Alloy.createController('listen').getView();
window.open();
})();
livebar.js
$.livebar_playpausebtn.addEventListener('click', function(event) {
if (audioPlayer.playing || audioPlayer.paused) {
audioPlayer.stop();
if (Ti.Platform.name === 'android')
{
audioPlayer.release();
}
} else {
audioPlayer.start();
}
});
// Add App eventlistener to listen for updateSingleProgessBar
Ti.App.addEventListener("app:updateLivebar", updateLivebar);
function updateLivebar(livebarText){
$.livebar_datalbl.text = livebarText;
Ti.API.info('State: ' + e.description + ' (' + e.state + ')');
}

Render HTML with images using PhantomJS

I am trying to create a PDF from HTML text using PhantomJS (version 1.9.7). I've written a very simple script (made more complicated by error callbacks etc.)
phantom.onError = function(msg, trace) {
var msgStack = ['PHANTOM ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
});
}
system.stdout.write(msgStack.join('\n'));
phantom.exit(1);
};
var page = require('webpage').create();
page.viewportSize = { width: 800, height: 600 };
page.paperSize = { format: 'A4', orientation: 'portrait', margin: '1cm' };
page.onResourceRequested = function(requestData, networkRequest) {
console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData));
};
page.onResourceReceived = function(response) {
console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response));
};
page.onResourceError = function(resourceError) {
console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
page.onError = function(msg, trace) {
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : ''));
});
}
console.error(msgStack.join('\n'));
};
page.content = "<html><body><b>test</b><img src=\"http://www.google.co.uk/images/srpr/logo11w.png\" alt=\"\" border=\"0\" /></body></html>";
page.render('tmp.pdf');
setTimeout(function() {
phantom.exit();
}, 5000);
I set up the page, assign the simple HTML string to the content property and render it to a PDF.
This script doesn't produce any output.
I've narrowed the problem down to the <img> element, when that is removed a PDF is generated as expected. I can see from the callback functions that the image is requested, a response is received, and there are no errors reported. I've tried rendering to a PNG which also yields no output.
I've explored the possibility of this being a proxy issue, however the raserize.js example works without any problems.
You have to call render when the page is fully loaded. Remember that loading a page via page.open or page.content is always async.
Change your code to this
page.content = "<html><body><b>test</b><img src=\"http://www.google.co.uk/images/srpr/logo11w.png\" alt=\"\" border=\"0\" /></body></html>";
setTimeout(function() {
page.render('tmp.pdf');
phantom.exit();
}, 5000);

Debugging PhantomJS webpage.open failures

In PhantomJS, webpage.open takes a callback with a status parameter that's set to 'success' or 'fail'. According to the docs, it wll be "'success' if no network errors occurred, otherwise 'fail'." Is there a way to see the underlying network error that caused the failure?
The url I'm trying to load works fine when I put it in my browser, and when I take a screenshot after getting the 'fail' message I see the page that I was on before I called webpage.open (so I can't just ignore the fail). I'm using Phantom for testing, so ideally I'd like a robust way of easily getting a helpful error messsage when webpage.open fails (or better yet have it never fail!)
Found this post which explains how to set up callbacks to get at the underlying reason for the failure: http://newspaint.wordpress.com/2013/04/25/getting-to-the-bottom-of-why-a-phantomjs-page-load-fails/
Based on the that page, you could print out errors as follows:
page.onResourceError = function(resourceError) {
console.error(resourceError.url + ': ' + resourceError.errorString);
};
The page goes on to show an example of detailed logging for phantoms
var system = require('system');
page.onResourceRequested = function (request) {
system.stderr.writeLine('= onResourceRequested()');
system.stderr.writeLine(' request: ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
system.stderr.writeLine('= onResourceReceived()' );
system.stderr.writeLine(' id: ' + response.id + ', stage: "' + response.stage + '", response: ' + JSON.stringify(response));
};
page.onLoadStarted = function() {
system.stderr.writeLine('= onLoadStarted()');
var currentUrl = page.evaluate(function() {
return window.location.href;
});
system.stderr.writeLine(' leaving url: ' + currentUrl);
};
page.onLoadFinished = function(status) {
system.stderr.writeLine('= onLoadFinished()');
system.stderr.writeLine(' status: ' + status);
};
page.onNavigationRequested = function(url, type, willNavigate, main) {
system.stderr.writeLine('= onNavigationRequested');
system.stderr.writeLine(' destination_url: ' + url);
system.stderr.writeLine(' type (cause): ' + type);
system.stderr.writeLine(' will navigate: ' + willNavigate);
system.stderr.writeLine(' from page\'s main frame: ' + main);
};
page.onResourceError = function(resourceError) {
system.stderr.writeLine('= onResourceError()');
system.stderr.writeLine(' - unable to load url: "' + resourceError.url + '"');
system.stderr.writeLine(' - error code: ' + resourceError.errorCode + ', description: ' + resourceError.errorString );
};
page.onError = function(msg, trace) {
system.stderr.writeLine('= onError()');
var msgStack = [' ERROR: ' + msg];
if (trace) {
msgStack.push(' TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : ''));
});
}
system.stderr.writeLine(msgStack.join('\n'));
};

How can i attach a value from Json Data to an Actionlink in mvc4

The data got from Json i used to append to a table as rows.First data of the column needs to come in Link format.So i used ActionLink .But i get the following error as "The name 'Transaction_No' does not exist in the current context".
function CreateGrid(result) {
$.ajaxSetup({
cache: false
});
for (i = 0; i < result.data.length; i++) {
debugger;
var chk_row = true;
$('#tbl_RoleMenu tbody').empty().append('<tr id="tr-' + i + '"></tr>');
String Transaction_No = result.data[i].Loan.toString();
$('#tr-' + i).append('<td id="tdLoan-' + i + '"> #Html.ActionLink(Transaction_No, "Create", "Portfolio", null, new { #class = "openDialog", data_dialog_id = "emailDialog" }) </td>');
$('#tr-' + i).append('<td id="tdLoan-1' + i + '">' + result.data[i].Loan + '</td>');
}
}
You seem to be completely mixing server side code with client side javascript. Try fixing this mess:
function CreateGrid(result) {
$.ajaxSetup({
cache: false
});
for (i = 0; i < result.data.length; i++) {
debugger;
var chk_row = true;
$('#tbl_RoleMenu tbody').empty().append('<tr id="tr-' + i + '"></tr>');
var transactionNumber = result.data[i].Loan;
$('#tr-' + i).append('<td id="tdLoan-' + i + '">' + transactionNumber + '</td>');
$('#tr-' + i).append('<td id="tdLoan-1' + i + '">' + result.data[i].Loan + '</td>');
}
}
As an alternative to this horrible mess I would recommend you create this markup on your server using a partial view. I guess that you are calling this function after performing an AJAX request to a controller action (that currently returns a JsonResult). Modify this controller action so that instead of returning a JsonResult returns a PartialView and then simply inject this new markup into your DOM.

How to add a function to another jQuery function?

I'm trying to add this short function - which swaps images according to the active tab in jQuery UI Tabs - below to the larger function below, which is the jQuery Address plugin that adds forward/back and #URL functions to UI Tabs: http://www.asual.com/jquery/address/
I need to add the shorter function so it fires when the tab changes - so it changes the image in #headerwrapper - but I can't quite tell exactly where the tab change is fired in the main address function. Any ideas on how to add this shorter function to jQuery Address?
Image change function I need to add to the main function below to run when the tab change fires:
var img = $(ui.panel).data("image");
$("#headerwrapper")
.animate({ opacity: 'toggle' }, function() {
$(this).css("background-image", "url(" + img + ")")
.animate({ opacity: 'toggle' });
});
}
Main jQuery Tabs Address function:
<script type="text/javascript">
var tabs,
tabulation = false,
initialTab = 'home',
navSelector = '#tabs .ui-tabs-nav',
navFilter = function(el) {
return $(el).attr('href').replace(/^#/, '');
},
panelSelector = '#tabs .ui-tabs-panel',
panelFilter = function() {
$(panelSelector + ' a').filter(function() {
return $(navSelector + ' a[title=' + $(this).attr('title') + ']').size() != 0;
}).each(function(event) {
$(this).attr('href', '#' + $(this).attr('title').replace(/ /g, '_'));
});
};
if ($.address.value() == '') {
$.address.value(initialTab);
}
$.address.init(function(event) {
$(panelSelector).attr('id', initialTab);
$(panelSelector + ' a').address(function() {
return navFilter(this);
});
panelFilter();
tabs = $('#tabs')
.tabs({
load: function(event, ui) {
$(ui.panel).html($(panelSelector, ui.panel).html());
panelFilter();
},
fx: {
opacity: 'toggle',
duration: 'fast'}
})
.css('display', 'block');
$(navSelector + ' a').click(function(event) {
tabulation = true;
$.address.value(navFilter(event.target));
tabulation = false;
return false;
});
}).change(function(event) {
var current = $('a[href=#' + event.value + ']:first');
$.address.title($.address.title().split(' - ')[0] + ' - ' + current.text());
if (!tabulation) {
tabs.tabs('select', current.attr('href'));
}
}).history(true);
document.write('<style type="text/css"> #tabs { display: none; } </style>');
</script>