Mobile website and desktop website : do I have to duplicate my code? - jquery-mobile

I have a website built with Symfony2 and I would like to create a mobile version of it using jQuery mobile (I'm currently using Twitter bootstrap for the desktop version).
I'm really confused about the solution I have to choose :
create a subdomain, for example : http://mobile.mywebsite.com and create another Symfony project which would be very similar but with just other html.twig files (to integrate jQuery mobile), but that means that I would duplicate a big part of my code ?
media queries inside my symfony project in html files to use jquery mobile elements according to screen size. Thus, I would have only one project to maintain.
Any advice would be great ! Thanks !

You can do routing based on the domain name:
http://symfony.com/doc/master/components/routing/hostname_pattern.html
With this you can have different controllers for the mobile site but still re-use your model and (at least some of) your view. You could even re-use some of the controllers by setting a parameter (based on the host) in the routing and then using that in the controllers:
# routing.yml
mobile_homepage:
path: /
host: m.{domain}
defaults: { _controller: AcmeDemoBundle:Main:homepage, mobileVersion: true }
requirements:
domain: %domain%
homepage:
path: /
defaults: { _controller: AcmeDemoBundle:Main:homepage }
Then in your controller:
// Acme/DemoBundle/Controller/MainController.php
public function homepageAction($mobileVersion = false) {
...
if ($mobileVersion) {
// do some mobile things, perhaps return a specific template
} else {
// do some non-mobile things, perhaps return a specific template
}
...
}

Best practice is to create one page with a responsive design (media queries are part of that) that can adapt to any screen size.
You definitely should not be making a second Symfony project. You are essentially trying to make 2 different layouts for your site, so they should only affect your view. If you don't want to use a responsive design, you can create twig templates for your mobile pages and load those from the same controllers you use for the desktop site.

I know it's a bit late but it still may be usefull for others.
I had the same question this morning and Google gave me MobileDetectBundle https://github.com/suncat2000/MobileDetectBundle/ which seems to solve that kind of problem. Not tryed yet but I will for sure !

Related

Angularjs Light version

I use angular in many projects, specially in ASP.NET MVC, but i dont like angular-
router (also ui-router, this is not much problem indeed as it's just a plugin) - concept of web-apps kills all ASP.NET features
services and factories - as all of this can be done inside common controller. (This might sound tricky)
constants and values - as i dont think this is really needed if you use requirejs or other AMD
What i love in angular is just directives, and when i make big nested directive, i use same controller foreach, so there is no $scope interacting (less watchers)
.controller('BaseGridCtrl', function(){
//instead of
//$scope.value = 123;
var ctrl = this;
//this is for Table-base-directive
ctrl.value = 123;
//this is for Table-head-directive
ctrl.value2 = 123;
});
.directive('table-base', function(){
return {
template: '<div>{{bgc.value}}</div>',
controller: 'BaseGridCtrl',
controllerAs: 'bgc'
}
});
.directive('table-head', function(){
return {
template: '<div>{{bgc.value2}}</div>',
controller: 'BaseGridCtrl',
controllerAs: 'bgc'
}
});
.directive('table-foot', function(){
return {
template: '<div>{{bgc.value3}}</div>',
controllerAs: 'bgc',
controller: function(){
var ctrl = this;
ctrl.value3 = 123;
}
}
});
So the link function is used veeery rare. And specially i like that angular easily detects directive - which is great as you just write 1 tag <grid> instead of reactjs components (This also might sound tricky). In my projects i use DotLiquid for razor views (it's stored in database as string) Sample:
<grid theme="some" route="localhost:9000/some/action"></grid>
So dotLiquid just renders this string w/o problem, or even applies other bingings beside angularjs. And this is great as all stuff is self contained. Which cannot be achieved by reactjs - you need to bootstrap components by yourself
React.renderComponent(<Grid />, document.querySelector('#someId'))
resume
Currently it's heavy, about 100kb, but without all this unnecessary stuff it would be really light. I would like to use only directive and controller services, Also with server-side rendering angular gonna bootstrap itself on each request which is not wise, but with lighter version it's a bit tradeoff.
Has anybody tried to strip angular services succesfully? Or is there any consideration, any ideas?
edit
Angular-light looks promising, but:
it doesn't provide HTML tag detection, only attributes
really ugly, alight.directives.al.getValue this looks so bad only for me or someone else?
edit2
Ok, that 100kb might not play alot. But consider it as workout, as you might know, angular start only once, at page load, so it must build the app, pull all modules, configure each, then all services of module, then inject them where they are needed, then supply callbacks from factories and services to any who injects them, at least it gonna check if any exists (on each module), all of this happens at start, only once! By wiping up size, we also can minimize javascript execution(indeed it will), factory and service watchers, so we won't need any parts that aren't used. We can even get rid of controllers (and use them inline), only 1 service. angular.directive (which is best part of party). Have looked at mustache, handlebars, but they are just like reactjs.
You can try Angular Light ~15kb (gzipped), it doesn't have services, factories, constants, values, DI, router and so on.
In addition, it has helpful features like text-directives and a support of Object.observe (benchmark)
edit
It provides HTML tag detection, attributes and comments.
AngularJS is meant for full SPA development. This means that you are not making full round trips to the server all the time. If your application needs to pass data back and forth, utilize the WEB API controllers and pass JSON up to them.
An Asset Management System I am currently working on is full SPA with WEB API and MVC fully wrapped into its needs. User log-in is processed across a full page request everything else is SPA. Additionally, here is something to read more about using MVC/WebAPI and Angular together.
If you are trying to use AngularJS instead of something like BackboneJS then you should be using AngularJS Light which was started for this exact purpose. I haven't used this library specifically, but as it is suppose to be an alternative to libraries I do use. The suggestion, if you want Angular and not BackboneJS or KnockoutJS use AngularJS Light

What kind of questions should be asked when choosing between straight MVC4 and a SPA framework like Durandal or Angular?

I'm in the middle of making this choice right now and I don't know what kinds of questions I should be asking. One that I believe is valid:
Do I need SEO / natively crawlable pages? If so, stick with MVC4.
One question that I'm not sure about is the impact on performance - I think this is valid:
Is initial load time very important? If so, stick with MVC4 (like stackoverflow).
What are some other questions that should be asked that can help point a developer in the right direction here?
PS - if this question is being asked in a way that doesn't meet quality standards, I'd appreciate any help modifying it so that it does.
I have been asked and had to be a part of decision making groups recently that made this same decision. Here is what was important for us -
How many of the devs that will be working are familiar with MVC4 vs Javascript?
How much is performance an issue? (Is single page app really necessary?)
How big is the data we will be working with? (Remember that extremely large data sets don't work well in a spa)
Durandal requires using a lot of different libraries - is it ok to have to learn each of the different usages? Each library is important in its own regard and you must know when and why to use each library.
Angular is very set in its ways and harder for a new javascript dev coming from c# and .net to understand, are you willing to provide time for learning?
Last, which browsers are you targeting? Ie6+ works great with mvc4 and durandal, angular needs some massaging.
Hope this is helpful!
Why not combine the best of both worlds? SPA and straight MVC!
I was also investigating a lot of time in durandal, sammyjs, angular frameworks. I then decided to go with sammy.js for just the routing. This way I could still make use of the easy MVC 4 razor view engine to generate my views at server side. Even though it would be more performant to generate your html and bindings at client side by using knockout, I felt more secure by doing this at the server side.
But then of course you have to deal with those hashbangs? Therefor I started to investigate more time into the history.js (or HTML 5 history API). And then things got clear to me.
My solution
What is the essential part of a SPA? Well, in fact, that your layout.cshtml is only loaded once right. From then on you you only want to load content from the server and display it in the main content div. Does it need to be json? No, in fact it does not.
By default MVC 4 controllers returns an html string. So what if your < a href="">< /a> tags would be intercepted by a simple jQuery script to get the html string from the controller and load it into a div.
I went even further and wrote my own jQuery engine on top of the HTML 5 history api. I just intercept every link that is clicked and load the content from its href attribute and then place it into the desired div. Further I push the URL with history api pushSate. Another big advantage of this approach is that your application is not broken when javascript is disabled or when HTML 5 is not supported.
My views have the following layout page:
#{
Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}
This way when javascript is disabled or html 5 is not supported, the view will render inside the _Layout.cshtml.
This also allows for URL linking. The link will hit the address bar and will be routed to the controller. As this is not an ajax request, the view will render with _Layout.cshtml.
But once your _Layout.cshtml and javascript is loaded correctly and once, all < a href="">< /a> will be intercepted, loaded by AJAX (partial with layout = null) into the content div and the url is pushed on the address bar. So it seems that you are at that location, but in fact you are not. It's just an illusion to make things more responsive and efficient. Et voila, SPA in straight MVC.
The minimum routing code would be something like this
Interception of Links
$('.spalink').click(function () {
$.ajax({
url: this.href,
success: function (content) {
$('body>#content').css({ opacity: 0 });
$('body>#content').html(content);
$('body>#content').animate({ opacity: 1 }, 300, 'swing');
history.pushState({ state : 'spa' }, null, this.href);
}
});
return false;
});
BACK and FORWARD event
window.addEventListener("popstate", function (e) {
if (e.state != null) {
$.ajax({
url: location.href,
success: function(content) {
$('body>#content').css({ opacity: 0 });
$('body>#content').html(content);
$('body>#content').animate({ opacity: 1 }, 300, 'swing');
},
cache: false
});
return false;
}
});
return true;
}
PS: if you don't feel like writing your own SPA engine, take a look at history.js (it does the same out of the box)
Ajaxify on top of History.js on top of HTML 5 history API

Backbone without Hashes?

I think I'm trying to use Backbone in an unintended way, and I couldn't really find much on it. Basically I have a Rails app that is serving up the views. I want to keep the regular navigation (as in page reloading), but let backbone see the route and setup certain parts of the templates on that page, handle the models, and all of that good stuff. So basically I'm using Backbone to handle all of my complicated javascript without making it a "single page app". Would enabling PushState break my absolute paths in older browsers? eg: "http://localhost:3000/projects" matching the route "projects".
PushState will not work in old browsers like IE6, but you could use different technique, for example you could use jQuery selectors and check whether you're on the particular page:
if ($('#login-page').length > 0) {
// we're on the login page
// ..initialize login page related backbone collections and views
}
..or you could store action/controller name somewhere in the html using data attribute: <body data-action="edit" data-controller="post"> and check it in javascript va4 $body = $('body'); if ($body.data('action') == 'edit' && $body.data('controller') == 'posts') {} etc.
..or you could have separate js file for each action/controller pair and include it on demand.

FCKEditor in asp.net-mvc

How to add FCKEditor in MVC application?
How to show database value comes in model, in FCKEditor?
That CodeProject website isn't ideal. It asks you to do alot of unneccessary code. All you really need to do is include the correct javascript file:
Then, in the page, render the FCKEditor, given any number of different ways. I prefer to replace a text area:
window.onload = function()
{
var oFCKeditor = new FCKeditor( 'content' ) ;
oFCKeditor.ReplaceTextarea() ;
}
At that point, the editor should load just fine. You will probably need to edit the fckeditor configuration files to get the standardized behavior you want. At this point, however, everything should just work. Your FCKEditor instance will behave just like another form field, and you can treat it as such when you get values from it on the server side.
It's very easy to create the server side api's for it to use as well. I created an fckeditor control, and you just need to implement GetFolders, GetFoldersAndFiles, and GetFiles. Those only take a few lines and give you nearly all the functionality you need.
I think it's easier to integrate / customize fckeditor using MVC than it is on Classic ASP.NET.

Using JQuery with ASP.NET MVC Framework

I have searched the forum, and google for this topic. Most of the articles are talking about using JSON to call the controller/action on the server and do ajax effect on the result.
I am trying to use some very basic JQuery features, like the JQuery UI/Tabs, and JQuery UI/Block for a dialog window. I cannot get these simple samples to work in my MVC project. Any ideas how I should modify these samples? I only need these basic feature now and I can go from here.
Thanks!
Actually I just got it working. The problem is that I need to modify the path to an absolute path to the view page because the relative path doesn't work with the MVC routes {controller}/{action}/{id}.
Thanks!
For info, re the relative path issue - I discussed this here (the same concept applies to any page, not just master pages). The approach I used is like so:
1: declare an extension method for adding scripts:
public static string Script(this HtmlHelper html, string path)
{
var filePath = VirtualPathUtility.ToAbsolute(path);
return "<script type=\"text/javascript\" src=\"" + filePath + "\"></script>";
}
2: when needed (for example in the <head>...</head>) use this method:
<%=Html.Script("~/Scripts/jquery-1.2.6.js")%>
The advantage of this is that it will work even if the web app is hosted in a virtual directory (i.e. you can't use "/Scripts" because you aren't necessarily at the site root) - yet it is a lot clearer (and less messy) than the full script with munged src, i.e.
<script ... src="<%=Url.Foo(...)%>"></script>
I just implemented the jquery autocomplete textbox in one of my asp.net project. I only had to import the js file and drop some code into my aspx page. Could you be more detailled about what sample you are trying to run?
This is quick response!!
I am trying to run this "Simple Tabs" on this page:
http://stilbuero.de/jquery/tabs/
I think it is the same with this one: http://docs.jquery.com/UI/Tabs
I just copied and pasted the whole thing into my MVC view page, with corrected path to the jquery.js and .css files, but the content in the tabs all show up together (two of them are supposed to be hidden). My understanding is that this simple jquery plugin just show and hide content.
I had the exact same problem with the jquery thickbox plugin, that the item marked as "hidden" (the dialog box) will always show up in my MVC view page.
I can understand some of the MVC+Jquery+json articles, but I don't understand why the hide/show doesn't work.
Thanks!
I just made a walkthrough on how to do this:
http://blogs.msdn.com/joecar/archive/2009/01/08/autocomplete-with-asp-net-mvc-and-jquery.aspx

Resources