Responsive Durandal dialog - javascript

I'm using Durandal in my new application and I have an issue with Durandal's dialog window (I'm using it to get some data from users).
When I set width of window manually, (by default Durandal set window position from JavaScript) and if I want to have window width 600px , I need to do that through CSS with .dialog { width: 600px! important}. and that's where all the problems starts.
On window resize, dialog is not responsive anymore, and when I have big form in it and window height is small, for example on laptops I cant see a half of my form and I don't get any scroll.
On mobile devices it's a total mess. Does anyone knows how to make this thing work?

I believe the Durandal modal is receiving love in Durandal 2.1 although I do not know if it will be responsive.
In the meanwhile, Durandal provides all the hooks you need to implement your own modal functionality - including the ability to define different types of modal dialogs. You can read more about it here:
http://durandaljs.com/documentation/Showing-Message-Boxes-And-Modals.html
I experimented briefly with this via some code found on google groups and was able to get bootstrap 3 modals working.
You're welcome to try it out and see if it works for you. Note that you must be using bootstrap 3 for this to work (durandal 2.0 starterkit etc comes with bootstrap 2)
In dialog.js, just before return dialog;
dialog.addContext('bootstrap', {
addHost: function (theDialog) {
var body = $('body');
$('<div class="modal fade" id="myModal"></div>').appendTo(body);
theDialog.host = $('#myModal').get(0);
},
removeHost: function (theDialog) {
setTimeout(function () {
$('#myModal').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
}, 200);
},
compositionComplete: function (child, parent, context) {
var theDialog = dialog.getDialog(context.model);
$('#myModal').modal('show');
},
attached: null
});
and then activate with:
dialog.show(viweModel, null, 'bootstrap')
or I believe this would work also but I didn't test it:
dialog.showBootstrap(viewModel)
And your view should follow the markup pattern:
<div class="messageBox">
<div class="modal-header">
Header Markup
</div>
<div class="modal-body">
Body Markup
</div>
<div class="modal-footer">
Footer Markup
</div>
</div>
Here is the gist where I got the code:
https://gist.github.com/webm0nk3y/7603042
And the relevant google groups thread:
https://groups.google.com/forum/#!topic/durandaljs/8g7DDCuvlpU

If you want to disable the width-setting for custom modals, you can add the following style definition to your outermost div:
<div style="width:auto;">
Please note that this can cause strange behaviour in some browsers.
If there is something else you would like to have for MessageBoxes or Modals, especially for their positioning and sizing, please let me know and I can make some changes to the code. My email is tommi.gustafsson at loyalistic.com.
UPDATE 14 Jan 2014:
I made a new revision of dialog.js, which helps with problems with customizing the MessageBox (not custom modals). You can find it at:
https://github.com/TommiGustafsson/Durandal/blob/master/src/plugins/js/dialog.js
(That's still unofficial, since it's in my fork of Durandal.)
You can find the instructions how to use it here:
https://github.com/BlueSpire/Durandal/pull/362#issuecomment-32180718
If you have problems with MessageBox, I think this might help you.

Related

Trigger MDBootstrap side-nav with jQuery using custom hamburger button

This was working fine:
http://jsfiddle.net/musicformellons/ef76gud7/
Now I would like to use MDBootstrap instead of Bootstrap and so I have to alter this jQuery code:
$(document).ready(function () {
$('#navbar').on('show.bs.collapse', function () {
$('#nav-icon4').addClass('open');
});
$('#navbar').on('hide.bs.collapse', function () {
$('#nav-icon4').removeClass('open');
});
});
to work with this side-nav (using my own animated hamburger, see fiddle):
http://mdbootstrap.com/javascript/sidenav/
I can trigger the side-nav with my hamburger by adding these to my hamburger button:
data-activates="slide-out"
class="button-collapse"
But then I loose the animation, since obviously the bootstrap navbar collapse is no longer shown.
How can I have my hamburger animation together with the new side-nav? Probably the cited jQuery code needs to be adjusted completely?!
So following is needed: (1) trigger MD bootstrap sidenav from another CSS button then its default one (2) the hamburger animation should stay 'in sync' with the sidenav. For instance: just using toggle it would probably loose sync as I had similar experiences before: Bootstrap navbar toggle not in sync with dropdown menu
You could use this fiddle as a starting point:
http://jsfiddle.net/musicformellons/rto14vzp/2/
Comments regarding the fiddle:
ignore the JS and CSS resource panel message; i tried adding
mdbootstrap via the resource panel and it did not work whereas
current approach does.
the reference to mdbootstrap (via CDN url) refers to the free part
of mdbootstrap (the side-nav is part of the free package).
The most direct answer to your question is that you need to chain the button animation and sideNav() opening triggers together with one jQuery statement. If you add .nav-icon-line to your spans, that would look like this:
$("#nav-icon4, .nav-icon-line").click(function() {
$("#nav-icon4").addClass('open');
$(".button-collapse").sideNav();
});
There is a lot more going on here that I can't really get into because the source of sideNav() isn't freely available with the framework you are using.
Something else to consider:
You'd need to reset the hamburger animation in the same way by using removeClass(). I'm not really sure how that would work because sideNav() is a black box. From what I can see, sideNav() seems to hide the sidebar when you click outside of it; figure out what function controls that and put $("#nav-icon4").removeClass('open'); into the function.
Codepen example (not fully functional yet, depends on figuing out what's happening inside of sideNav).

jQuery drop in Social Sharing Buttons at the Bottom if inline buttons are not on screen

I'm looking for an Event which is triggered as soon as an Element (inline sharing buttons) scrolls out of page. I'd like to use this to trigger the drop in of social sharing buttons from the bottom of the page. You may have seen such side behaviour already on buzzfeed.com on mobile devices. If the sharing buttons come back in, the bottom sharing buttons should fade out again.
I'd prefer to only use CSS3 however I think some js (jQuery) may be necessary.
Anyone knows a library or some lines of code doing this?
Thx I really appreciate your expertise!
You could try like this
JS:
$( window ).scroll(function() {
if($( window ).scrollTop() >= socialButton.offset().top + socialButton.outerHeight())
hiddenSocialButton.stop().animate({'bottom': 0}, 100);
else
hiddenSocialButton.stop().animate({'bottom': -hiddenSocialButton.outerHeight()}, 100);
})
jsfiddle demo
Please refer to this question. Used the reference to code this
HTML :
<div class="container">
<div class="social_links">Social Links</div>
<div class="bottom_links">Bottom Links</div>
</div>
JS :
function triggerFunction()
{
if(isScrolledIntoView('.social_links'))
{
$('.bottom_links').fadeOut();
}else{
$('.bottom_links').show();
}
}
DEMO HERE

Angularjs - Jquery loading

I have somesthing strange happen here.
I got the following directive:
app.directive('addscroller', function () {
return function (scope, elm, attrs) {
// jQuery Script triggern
// AngularJS: jQuery(selector) = element.
elm.ready(function () {
elm.nanoScroller({ alwaysVisible: true });
})
}
});
I'm adding it to this code:
<div ng-show="datenschutz" class="alldealermodal">
<p ng-show="loading">Loading...</p>
<div>
<h1 class="headline">DATENSCHUTZ</h1>
<div class="closebtndiv">Close</div>
<div class="clear"></div>
<div class="nano" addscroller>
<div class="content"><p>BIG LONG TEXT</p></div>
</div>
</div>
<div class="fadeout"></div>
</div>
On click on this link,
<p>Datenschutz</p>
it opens the overlay "datenschutz" as seen above (ng-show="datenschutz"). The toggle works great BUT....
When I directly open the div after the page shown up, I see the scroller loading and appearing fine. It works.
But If I wait some moments, just a few seconds and then I open the "datenschutz"-overlay, the scroller isn't loaded and doesn't load at all.
I have something similar for a second overlay and this happens too.
EDIT / UPDATE:
I figured out, that the problem is, that jQuery cannot apply the script to an element which is hidden. When I quickly open the div before the $last element in the ng-repeat (inside the div) has loaded, it works, because the div is visible.
Does anyone know a workaround for that?
Solution 1 (Quick and Dirty):
Used AngularUI fpr the "ui-toggle" directive. It toggles ui-hide or ui-show as class into the element.
Afterwards used this CSS:
.ui-show {opacity:1;visibility: visible;}
.ui-hide {opacity:0;visibility: hidden;}
Worked for me in Chrome 24 and Firefox 18.
If someone got some other solutions, please post. My solution is maybe not the best one.

Scrolling in web application in iOS with iScroll

I have a few web applications that were previously developed for use in Android apps, and we're trying to port them to iOS.
The first problem was that the ad we had was not staying in place, since position:fixed is no good in mobile Safari. So, I downloaded iScroll.
I figured out that iScroll doesn't play nice with our RSS feed reader (zRSSFeed for jQuery). In fact, when both are enabled on the same page, the iScroll functionality "works", but gets stuck at the top of the page.
I posted to the iScroll user group (https://groups.google.com/group/iscroll/browse_thread/thread/5dd274ff4159a672) but got no useful answers.
I even tried to change to a different RSS library, but it seems they all elicit this issue.
Has anyone had this issue before? Has anyone solved it? Should I just give up and put the ad at the bottom of the webapp, or what?
Thanks, all.
EDIT: I figured I should add in a bit of code.
Basic structure of web stuff:
....
<div id="appBody">
<div id="feedResults">
<!-- rss entries go here -->
</div>
</div>
<div id="appAdvertisements">
<!-- admob JS stuff goes here -->
</div>
....
Basic JS:
var scroll;
document.addEventListener('touchmove', function (e) { e.preventDefault();}, false);
function loaded() {
scroll = new iScroll('appBody');
$('#feedResults').rssfeed('<feedurl>', {<options>}, function() { scroll.refresh() });
}
document.addEventListener('DOMContentLoaded', loaded, false);
I would suggest you first populate the #feedResults with your parsed rss and oncomplete of this action, you start the iScroll. Don't start both at same time nor use refresh() without setTimeout like Matteo said in iScroll4 documentation.
Considering the function() after stands for the onComplete, try something like this:
var scroll;
function loaded() {
$('#feedResults').rssfeed('<feedurl>', {<options>}, function() {
scroll = new iScroll('appBody');
});
}
document.addEventListener('touchmove', function (e) { e.preventDefault();}, false);
document.addEventListener('DOMContentLoaded', loaded, false);
I think that will give time to the DOM to have your rss on it and then iscroll will calculate the correct height of your entire wrapper (appBody in this case).
I just had the exact same problem. The solution for me was to add position: absolute; to the element directly inside your wrapper, in your case you would need to add position: absolute; to feedResults.
In HTML5 based application, smooth scrolling is always challenging. There are third parties libraries available to implement smooth scroller but there implementation is very complex. In this scroller library, user only need to add scrollable=true attribute in the scrollable division, then that div will scroll like smooth native scroller. Please read readme.doc file first to start working on it
library link
http://github.com/ashvin777/html5
Advantages :
1 No need the manually create scroller object.
2 Scroller will automatically refreshed in case of any data being changed in the scroller. 3 So no need to refresh manually.
4 Nested Scrolling content also possible with no dual scrolling issue.
5 Works for all webkit engines.
6 In case if user wants to access that scroller object then he can access it by writing “SElement.scrollable_wrapper”. scrollable_wrapper is id of the scrollable division which is defined in the html page.

jQuery Mobile rendering problems with content being added after the page is initialized

I'm using jQuery Mobile and Backbone JS for a project. It's mostly working, using jQuery Mobile's event 'pagebeforeshow' to trigger the correct Backbone View. In the Backbone View for that particular jQuery Mobile page, that's where it's doing all the dynamic things needed. Some of the things the views do is pull in certain bits using Underscore's templating system.
This is all great until where I pulling in form bits using the templating system. For example, a set of dynamic radio buttons (which are generated from a Backbone Collection). These radio buttons I want to style up using what jQuery Mobile has to offer. At the moment, jQuery Mobile is not picking up these dynamically injected radio buttons. I solved this issue previously when doing sliders by just calling the jQuery Mobile widget "slider()" method again and it seemed to refresh them... This doesn't seem to be the case with these radio buttons.
In the Backbone View, I tried calling the widget methods again:
$(this.el).find("input[type='radio']").checkboxradio();
$(this.el).find(":jqmData(role='controlgroup')").controlgroup();
I tried them the other way around too, but it seemed I need to do it this way for the grouping styling to work etc. But this just doesn't seem right! ...doing this also caused errors when I clicked on the radio buttons, saying: "cannot call methods on checkboxradio prior to initialization; attempted to call method 'refresh'"?
It seems there should be a way in jQuery Mobile to re-initialize the page or something?! I noticed there is a 'page' widget in the source code.
How does jQuery Mobile handle forms/elements being injected into the DOM after the page is made? Is there a clean way of handling how it makes up the forms? There must be a clean way of calling on the forms to render 'the jQuery Mobile way' without it just relying on data attribute tags in the base HTML?
Any help or insight into this problem would be greatly appreciated... I'm very much on this quest of trying to get Backbone JS and jQuery Mobile to work nicely together.
Many thanks, James
update
Since jQueryMobile beta2 there is an event to do this. .trigger('create') on an element to cause everything inside it to be painted correctly.
Another question that is not a duplicate, but requires an answet I posted over 10 times :)
[old answer]
try .page()
More details in my faq:
http://jquerymobiledictionary.pl/faq.html
Refreshing the whole page worked for me:
$('#pageId').page('destroy').page();
I'm not sure if this helps but when adding dynamic elements I was using .page() in the sucess ajax call itself (example here and here) but I found that it was not working as expected. I found that in the ajax call it's better to refresh the element (if it's a form element) to use these documented methods:
Checkboxes:
$("input[type='checkbox']").attr("checked",true).checkboxradio("refresh");
Radios:
$("input[type='radio']").attr("checked",true).checkboxradio("refresh");
Selects:
var myselect = $("select#foo");
myselect[0].selectedIndex = 3;
myselect.selectmenu("refresh");
Sliders:
$("input[type=range]").val(60).slider("refresh");
Flip switches (they use slider):
var myswitch = $("select#bar");
myswitch[0].selectedIndex = 1;
myswitch .slider("refresh");
and for adding a non-form element use .page()
JQuery Mobile now supports .trigger("create"); which will resolve this for you
Try calling .trigger("create") on the element with the new content.
I needed a way to dynamically refresh a JQM page after it had been initialized. I found that if I removed the data attribute "page" during the "pagehide" event, the next time the JQM page was displayed it was re-initialzed.
$('#testing').live('pagehide', function (e) {
$.removeData(e.target, 'page');
});
$('#pageId').page('destroy').page();
works for entire control groups that are generated, let alone radio input children.
-Mike
It worked for me when I called .trigger('create') on the enclosing div element. See example below:
In .html file:
<div id="status-list" data-role="fieldcontain">
<fieldset data-role="controlgroup">
<legend>Choose as many snacks as you'd like:</legend>
<input type="checkbox" name="checkbox-1a" id="checkbox-1a"/>
<label for="checkbox-1a">Cheetos</label>
</fieldset>
</div>
in .js file:
$("#status-list").trigger('create');
For me only .page() worked (without the .page('destroy')).
E.g.:
$('my-control-group-id').page();
Amnon
I little bit off topic. I wanted to be able to stop jqm from creating first default page div on init as backbone wraps elements in divs anyway. I wanted to dynamically insert pages to the DOM and then call jqm to create its classes and widgets. I finally did this like this:
<head>
<script src="jquery-1.8.3.js"></script>
<script type='javascript'>
$(document).on("mobileinit", function () {
$.mobile.autoInitializePage = false;
}
</script>
<script src="jquery.mobile-1.3.0-beta.1.min.js"></script>
</head>
<body>
....... dynamically add your content ..........
<script type='javascript'>
$.mobile.initializePage()
</script>
</body>
and my hole jqm config (which you put before jqm.js)
$(document).on("mobileinit", function () {
$.mobile.ajaxEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.linkBindingEnabled = false; // delegating all the events to chaplin
$.mobile.changePage.defaults.changeHash = false;
$.mobile.defaultDialogTransition = "none";
$.mobile.defaultPageTransition = "slidedown";
$.mobile.page.prototype.options.degradeInputs.date = true;
$.mobile.page.prototype.options.domCache = false;
$.mobile.autoInitializePage = false;
$.mobile.ignoreContentEnabled=true;
});
So far Backbone and JQM been working fine.
Try use enhanceWithin() method. This should be method of any jQuery object while using jQuery Mobile.

Categories