I chose jQuery Mobile over other frameworks for its animation capabilities and dynamic pages support.
However, I'm running into troubles with styling. I'd like to keep the basic page style in order to perform page transitions. But I also need to fully customize the look'n feel of headers, listviews, buttons, searchboxes... Dealing with colors only is not enough. I need to handle dimensions, positions, margins, paddings, and so on.
Therefore I struggle with extra divs and classes added by jQuery Mobile in order to override them with CSS. But it is so time-consuming, and it would be way faster to rewrite css from scratch...
Is there a way to load a minimal jQuery Mobile css file ?
Or should I look towards an other mobile framework ? I need to handle page transitions, ajax calls, Cordova compatibility, and of course a fully customizable html/css...
Methods of markup enhancement prevention:
This can be done in few ways, sometimes you will need to combine them to achieve a desired result.
Method 1:
It can do it by adding this attribute:
data-enhance="false"
to the header, content, footer container.
This also needs to be turned in the app loading phase:
$(document).on("mobileinit", function () {
$.mobile.ignoreContentEnabled=true;
});
Initialize it before jquery-mobile.js is initialized (look at the example below).
More about this can be found here:
http://jquerymobile.com/test/docs/pages/page-scripting.html
Example: http://jsfiddle.net/Gajotres/UZwpj/
To recreate a page again use this:
$('#index').live('pagebeforeshow', function (event) {
$.mobile.ignoreContentEnabled = false;
$(this).attr('data-enhance','true');
$(this).trigger("pagecreate")
});
Method 2:
Second option is to do it manually with this line:
data-role="none"
Example: http://jsfiddle.net/Gajotres/LqDke/
Method 3:
Certain HTML elements can be prevented from markup enhancement:
$(document).bind('mobileinit',function(){
$.mobile.keepNative = "select,input"; /* jQuery Mobile 1.4 and higher */
//$.mobile.page.prototype.options.keepNative = "select, input"; /* jQuery Mobile 1.4 and lower */
});
Example: http://jsfiddle.net/Gajotres/gAGtS/
Again initialize it before jquery-mobile.js is initialized (look at the example below).
Read more about it in my other tutorial: jQuery Mobile: Markup Enhancement of dynamically added content
...or just use the official, theme-less version of the CSS built specifically to allow the design of a custom theme while maintaining all of jQuery Mobile functionality.
You don't have to fight with hacks and overrides all the time and you get a lighter CSS.
Win-win.
edit: Also answered here
To be honest i'm fairly disappointed that jQuery mobile didn't provide us with a relatively style-free starting kit, to work merely with what you have said: Ajax, transitions, cordova...
Overriding the generated css classes is absolute madness, but I have done some skunk work and I managed to reduce the uncompressed css file size from a whooping 233kb to merely 27kb, while keeping the important aspects of the css such as transitions, one-page viewing, etc. This way you start almost as you would start with an empty css file.
Perhaps I will upload the file on Github, if there's any demand for it. I wish to do some more testing to see that I didn't leave anything significant behind.
as of jQuery Mobile 1.4.0, the data-enhanced data attribute was added to most of components. Setting this as true attribute will cause jQuery mobile to ignore style enhancement for the component, so you'll have to style the element by your own.
additional information about this in the jQuery Mobile 1.4.0 release notes here
http://jquerymobile.com/upgrade-guide/1.4/
i m nô expert but i would love to share à weird method with you . Actually, it s very hectic task : what you need is to edit the jqm css line by line by deleting the property values just leave them blanks before ; you have just to look after the desired sections of the CSS file to adjust or delete value
Do not forget to attach your link rel of your own CSS at the head of your HTML page
I hope it will work for you
Related
I am working on a simple Cordova app with about 4 page types and I am trying to think through which is the better way to handle the inner HTML templates.
Hidden HTML hard coded into the HTML files that is hidden and populated/revealed by my JS.
Using a JS template system and appending and removing from the DOM.
I feel that appending all that to the DOM for a page is inefficient when I could just update the sections that change. But perhaps an append is lightweight enough where I shouldn't worry about it.
There are a number of ways you can do it. In terms of load on the browser. That is hard to say. From your question it is hard to know what is in these pages, what are you displaying, is it live data, static html etc.
When you first plot out an app, if you are from the old class of building multiple page websites, it can be a little concerning as to how well your app/page will run with all those pages crammed in to one, and all that data plus code.
The answer is, amazingly well. If done properly in modern browsers, and for example Ipads the app will run to near native performance.
The options you have are
Map all the pages into one HTML document. Hide each page content using css display:none, flip them into view using css animation, fading or just display:block.
Use a javascript routing library to map urls to blocks of code that deal with each page, this makes mapping out your app much easier, and means that buttons can just link to your pages, like a real website. see http://projects.jga.me/routie/
Building all the page templates into one page can make it hard to code, as the page becomes enormous, consider breaking the inner content of each page into separate files, you can then give each page holder a url and use a small xhr request to load the page on-the fly, once loaded you can cache it into memory or even local-storage, depending on whether you remove it when it is closed or keep it hidden.
In my experience you can put an enormous number or nodes into one page and have very little speed drop, bear in mind if you use something like jquery and do a lot of $(".page > .page1 > .items li") your going to have a slow app.
Tips
Use element ID's everywhere document.getElementById(..) is 100's of times faster in a loop that $(...)
cache elements when you find them, if you need them later store them in a memory cache.
keep for loop inner code to a minimum.
use a decent click touch libary like http://hammerjs.github.io/ and delegate all the events of the body tag or at least on each page.
If you need to touch the server, load data, think dom first, device second server later. A good app is a responsive app, that responds to the user instantly.
I know this has been posted a while ago, but for the sake of the users I am going to add my answer.
I completely agree with MartinWebb but my answer will shed some light on the results of his options. I am currently working on a similar project. Please note that this answer pertains to cordova (previously called phonegap) specifically. My app has about 5 pages with +-20 different components (input's, div's, h1's, p's, etc.). This is what i tried and the result of each:
jQuery was my first option, mainly because it is easy to use and reduces the amount of code required to accomplish a said goal. Result: First time I tried this approach I though I would spice it up with animations and transformations. The result of this was a very unresponsive app. I removed the animation and transformation, however due to the nature of my application I required multiple dynamically added components and jQuery just wasn't up for the task.
Css display:none and visible:hidden was my next option. I used javascript's dom to display certain div's. Result: This works if your not planning on switching many div shortly after one another eg. a simple menu. It quickly became apparent that this wasn't going to work. Also this does not eliminate my need for the dom. Remember document.getElementById('menu').style.display = "none"; is still part of the dom. This as a solution, for me, is poor. There is a reason that var menu= document.createElement('div'); is part of the language. Which brings me to my last option.
Building a page 90% on javascript's dom was my last option. Logically I could not see how 600 lines of code cold trump one .innerHTML or .style.display = "block"; but it did. Result: It was by far the most responsive of all the solutions.
I'm not saying that all webpages should be coded with dom appending, but as I stated previously, for a cordova app of a few pages (<6), with a few components a javascript dom appending approach would be best. It takes longer to code, but you will be rewarded with control and efficiency. I would suggest coding the backbone of your app in html and populating and controlling with javascript's dom.
Best of luck.
The first option, <div>s with display:none; would be more efficient by a small margin, but you can get the best of both worlds by compiling your JavaScript and templates together into a single file using something like browserify or require.js.
This may be a naive question, but I'm learning jQuery Mobile and unsure why everything is related to a data-role attribute. It seems that even times when the role is related to the style, they are using data-role over class
I understand that for semantics, data-role makes sense in a lot of cases but it just seems to be abused here. Wouldn't that kind of lookup also be slower?
Why do they use data-role over class?
Thanks for any insight.
Why data
They could simply use role as an attribute (like other frameworks do), but this would make
the resulting HTML invalid. Therefore a data- is added to every attribute name.
Why not classes
I think the main reason for that is to separate view from logic as far as it is possible. In larger projects, CSS and JavaScript are not written by the same person.
It provides a lot of control over powerful styling techniques especially when combined with jquery ui. I use jquery mobile, I used their tool to easily make a theme roller and now when I use elements like data-role-header, footer listview. I have great looking pages with no effort. There are hundreds of data-role attributes you can bring into your code to easily create uniform, user friendly pages. I personally like the data-role - page attribute to create multiple views in a single HTML page. They are easy to use so the best way to learn about them is to play with them.
Please find the explanation of data-roles here.
data-role attribute is used to control the behaviour of the widget of element. For example in case of button you can use input type="button" (no data-role="button" attribute required in this case, as this is standard behaviour of this element) but you can use a element, and then you need to explicitly provide it:
So for me it's rather useful solution, as buttons behavior on mobile devices can be same for different elements. You just need to provide data-role attribute, and jQuery will do the rest for you.
This is the quotation from main jQuery Mobile website:
jQuery mobile framework takes the "write less, do more" mantra to the
next level: Instead of writing unique apps for each mobile device or
OS, the jQuery mobile framework allows you to design a single
highly-branded web site or application that will work on all popular
smartphone, tablet, and desktop platforms.
They want to style every control you have in the same way, so write less, do more approach is fulfilled. So jQuery Mobile adds same styling for all elements with the same role to make things look the same way, but it doesn't mean you can't change it. It just means that they care about good look of your website, and they are aware that every button should be similar to others.
Also the page I mentioned earlier says:
The jQuery Mobile framework uses HTML5 data- attributes to allow for
markup-based initialization and configuration of widgets.
So you are reading HTML and you know how elements will behave without looking to CSS file - which I think is cool if you're not front-end dev. Of course front-end dev can overwrite CSS, but he must follow the rules, e.g. if data-inline is set to true he should style it regarding that elements must naturally follow this rule (be inline).
jQueryMobile adds a load event handler to the page, which processes the DOM looking for various data-xxx attributes. When it finds those, it does more than just stylize the elements.
In many cases it creates a type of widget tied to the data-role. For example, a <div data-role="header"> is turned into a toolbar widget, the creation of which may extensively modify the DOM within that element.
For some of the simpler widgets, like buttons, folks have seen that not much happens other than some classes get added, so why not just shortcut the process and do that directly? That can work, but it isn't future-proof. At different points in history, different versions of jQM had created buttons with different DOM structures. So I personally think it's best not to shortcut jQM, and let it process the data-attributes as it sees fit.
That being said, it would still have been possible to create widgets identified by classes rather than data-attributes, which was how people used to do these things before jQM. But then there might be an expectation that there would be CSS associated with those classes as well. Use of the data- attributes makes it clear that this is a structural/role thing rather than just styling.
I am not quite sure what the best (or most common practice) is when needing HTML elements for your JQuery plugin to work. For example (although contrived), if you required a spinner (ticker) plugin where you would have text box containing a number and to the left of the box a up and down arrow. When the up arrow is clicked the value is incremented and the value is decremented when the down arrow is clicked.
I see some JQuery plugins, especially the JQuery UI widgets, that expect you to supply all the html and to give them special classes.
In the case of the spinner would you just expect the input tag and then in the JQuery plugin generate the HTML to render the up and down buttons?
Perhaps a better example is something like creating a paging data grid. Would the paging buttons (First, Last, Previous, Next, Page 1, Page 2...) be generated by the plugin or should the user of the plugin be expected to create HTML with special classes.
You should look into jqGrid. It generates a lot of HTML, but it leaves the <table> and pager elements up to you. It then obviously appends to these elements. But it also creates siblings and containers for these elements as well.
For example,
<!-- index.html -->
<table id="mygrid"></table>
<div id="pager"></div>
// main.js
$('#mygrid').jqGrid({pager: '#pager', ...});
jqGrid not only appends to #mygrid and #pager, but also creates new siblings and containers.
<div id="gbox_mygrid">
<div class="ui-jqgrid-view">
<table id="mygrid"><!-- rows --></table>
</div>
<div id="#pager"><!-- stuff --> <?div>
</div>
So you see that jqGrid does what it has to do, to work well. I think it depends on the needs of the plugin.
Generally, I would expect the developer to supply only the container element along with any essential inner elements (think images in a slider). I would expect the plugin to generate any controls like buttons, pagination, etc.
Requiring the developer to supply a container element gives them complete control over how, when, and where your plugin appears on their page, as if it was just another div. Requiring them to also supply any necessary content isn't always necessary, as this could just as easily be a config item.
The main upside I see to having the user supply HTML comes when dealing with clients that don't support/allow JavaScript (think old browsers, spiders, etc). At least they'll see something related to what your plugin was meant to display, rather than just an ugly blank space. In the slider example, if done properly, the plugin can gracefully degrade to a static image in the case of lacking JavaScript support.
All intricacies such as controls and status displays should always be generated by the plugin. Why? User-friendliness is the first thing that comes to mind. People use jQuery plugins because they want a fast, relatively pain-free solution to a problem. Additionally, many users of jQuery plugins are not web developers, but instead are often just administrators of blogs and such.
By eliminating the need for the users of your plugin to have to create elements that they really have no control over, you also eliminate a lot of headaches caused by typos, misunderstandings, and lack of RTFMing.
Hopefully my opinions and insights have been helpful.
Seems like to me there should be an option for that but i can't seem to find it.
This question was asked many times but only workarounds were answered and that's not what i'm looking for.
I am changing my css incode and i want to load the original css back instead of coding it myself, how can that be achived?
I don't wanna reload the entire file, just load some div or class css.
See this post for a solution.
Based on that you can do something like this:
$("#fix").click(function(e) {
e.preventDefault();
$("div").removeAttr("style");
});
Note: This assumes you are using JQuery to change the styles in the first place
Here is a working example
if you're using jQuery apply
$(selector).removeAttr('style')
to your elements
I want to load the original css back instead of coding it myself
This is not necessary. You are trying to reload a resource that should just continue to exist. Once it's loaded, you don't need to load it again. If you need to override a style, apply a class to it. To revert to original, remove the class. That's how cascading style sheets work.
If there is a particular reason the css needs to be dynamic, you can try loading css into the Document via the DOM (document.createElement("style") etc.), but support for this is a bit sketchy I believe.
if you want to reset the WHOLE style and not only divs' you'd better use the all selector
$('*').removeAttr('style');
As I know that in JQuery Mobile, every page changing is equivalent to create new "page" div, Can we just change a portion in the "content" of the page, something like subpage?
jQuery Mobile doesn't require you to manage pages by creating additional div element in the same HTML file - you can do it perfectly fine in a different HTML file and make a transition to it (perhaps with data-prefetch attribute set) using <a>.
Nothing prevents you from writing a jQuery plug-in, jQuery UI plug-in or (scary though, I know) pure JavaScript that will alter the contents of the DOM element dynamically and manage pages loading according to data received from server - with necessary calls to things of the listview('refresh') ilk - to ensure proper styling.
With that said you have to ask yourself two things:
Why do you need to do it? Can't you manage by pre-creating the page using jQuery Mobile paradigm and just retrieving and inserting the data into the new page?
What will the performance implication (if any) will be, if I have to perform DOM manipulations on every 'page transition'?
As a side note - jQuery Mobile provides you with methods that allow for page manipulation:
$.mobile.changePage and $.mobile.loadPage that you can use (look at pageContainer option).
See API docs here
I am trying to use right now a jQueryMobile plugin for subpages: https://github.com/ToddThomson/jQuery-Mobile-Subpage-Widget
I didn't make it work yet but i think it should work :).