I am trying to configure a JavaScript function to sort of 'reload' on a particular web page. The site has an overarching JS and CSS framework, but I just want this particular function to load a bit differently.
The JS function in the JS framework sets the height of a grid element dynamically. For example, if I have three elements that have a height of 155px, 34px, and 100px, it takes the element with the highest value and applies that height to all of the grid elements, making them all 155px.
For the rest of the pages in the site, the code is fine because the JS script executes on page load. However, the page I'm using the function on doesn't seem to adhere to the JS script. It still retains differing heights when it is supposed to have the same height.
What's different about this particular page is the application coded in it. There is a filtering application in the page that features a Search text box and a checkbox similar to Amazon's application filters for categories like Men's or Women's clothing. However, unlike Amazon, checking/unchecking the checkboxes or typing something else in the Search box simply loads/reloads the 'content' but the page doesn't actually reload and the content are simply links. The links are loaded from a separate XML file.
The links in this case are the grid elements. They are set up to look like interactive buttons.
Here is the code for the JS function:
(function ($, window, document, undefined ) {
'use strict';
// add initialisation
this.addInitalisation('equal-heights', function() {
this.debug('Module: Equal Heights');
var font = new FontFaceObserver('BentonSansRegular');
font.load().then(function () {
// console.log('Font is available');
$(".grid > .grid-item").matchHeight();
});
});
// Register UI module
this.UIModule({
module: 'equal-heights',
init: function() {
this.initialize('equal-heights');
}
});
})( jQuery, window, window.document );
I didn't really upload a whole lot of the code because I am seeking to understand on how to solve this problem conceptually (provided that I was clear in my explanation of the issue).
To iterate my goal, I want to load the grid items in this particular web page to be the same height even after clicking/typing through the filter application.
Please let me know if I can clarify anything else.
This answer has been solved. What I did (what worked) was take this piece of code: $(".grid > .grid-item").matchHeight(); and place it in the JavaScript file that the particular web page used. This code is what sets the element height dynamically.
Related
This would be a generic question asked a number of times before. The reason why i am asking this is because i did use the on ready call back in jquery and it did not modify the placeholder of my element "search_input"
$( document ).ready(function() {
$("#search_input").attr('placeholder','New data that will be shown');
}
This is because the CSS is applied on the id "search_input" before it is loaded. I have tried everything but nothing seems to work.
Any ideas?
Note : I am working on ArcGIS Javascript to applications using ERSI maps . The issue i face is occurs when I load a search bar through javascript, which takes time to load the search bar. But my html page calls the on ready callback before this script is loaded. Hence, I face this issue. I am unable to solve this and any help would be appreciated!
I fixed this in my code using this,
search.on("load", function () {
//push all the sources
var sources = search.sources;
sources.push(addSources("ABC","ABC","eg : ABC",1));
sources.push(addSources("XYZ","XYZ","eg: XYZ",1));
search.set("sources", sources);
//Adding the placeholder here, as the search bar is loaded with sources only at this point of the execution
//Hence, we can modify the CSS only after this point.
$("#search_input").attr('placeholder','Search Tree Data');
});
You cannot modify the CSS anywhere in the code. It has to be modified only when the search bar has been loaded with all its sources. I tried adding a $document.ready(function(){}); or adding the css at the end of the body. Nothing worked because we are using a different javascript library/toolkit here - Dojo. Hence, we can only performs operations based on how the data is loaded or when call backs are called in Dojo. and not in normal HTML javascript to jQuery.
I'm using Processing.org looking at the example variableInputs in javaScript mode (can't find it online, but it is included with the download)
It has two tabs, one java and one .js. And a cool example on how to pass data around both.
In the first tab there are some HTML/CSS commented out. Those are building the page when I hit run...
How's that working?
Is it possible to have for instance more than one drop down menu (selector) side by side? I managed to have them, but always one below the another.
Is the way to go to edit the html in the first tab?
help?
do you need me to copy and paste the example here?
[EDIT]
When I hit export, the PDE exports:
index.html
processing.js //(the library it self)
interface.js //(the second tab in the PDE)
sketchName.pde //(the usual pde)
The html tags from above the code are included in index.html, so it can be edited there. Not sure though this is inserted in the html page. So putting the menus side by side turns out to be a HTML question I think... What i also don't know how to do :), but I'll look for it
[edit2] or perhaps a javaScript question... As is interface.js that is making th econtrols... How to control the position of them?
[edit3] well tuns out that the line
<form id="form-form"><!-- empty --></form>
is doing the link, via th id form-form...
Still is it possible to have some menus side by side inatead of one below another?
It is indeed a css/html issue as bfavaretto suggests. In order to do what you asked for try this:
style section in comments (java tab), essentially you have to make the two drop downs' width smaller (45%) and then css hacks to bring them inline, float:left or right
* <style>textarea,input,label,select{display:block;width:95%}select{width:45%;clear:none;float:left}
* input[type=checkbox],input[type=radio]{width: auto}textarea{height:5em},</style>
setController() method, add another ctrl.addMenu(); as such:
element = ctlr.addMenu( "theMenu", menuItems );
element = ctlr.addMenu( "theMenau", menuItems );
The problem after this is that the two labels block the two menus from coming in-line thus you probably have to remove them from these elements and add them manually. In the javascript tab comment out line 157:
//form.appendChild(label);
This line is in function this.addSelection = function ( l, o ) {
I was wondering how can I enhance dynamically jQuery Mobile page?
I have tried to use these methods:
$('[data-role="page"]').trigger('create');
and
$('[data-role="page"]').page();
Also how can I prevent enhancement markup of check boxes only?
Intro:
There are several ways of enhancing dynamically created content markup. It is just not enough to dynamically add new content to jQuery Mobile page, new content must be enhanced with classic jQuery Mobile styling. Because this is rather processing heavy task there need to be some priorities, if possible jQuery Mobile needs to do as less enhancing as possible. Don't enhance whole page if only one component need's to be styled.
What does this all means? When page plugin dispatches a pageInit event, which most widgets use to auto-initialize themselves. it will automatically enhance any instances of the widgets it finds on the page.
However, if you generate new markup client-side or load in content via Ajax and inject it into a page, you can trigger the create event to handle the auto-initialization for all the plugins contained within the new markup. This can be triggered on any element (even the page div itself), saving you the task of manually initializing each plugin (listview button, select, etc.).
With this in mind lets discuss enhancement levels. There are three of them and they are sorted from the less resource demanding to higher ones:
Enhance a single component/widget
Enhance a page content
Enhance a full page content (header, content, footer)
Enhance a single component/widget:
Important: The below enhancement methods are to be used only on current/active page. For dynamically inserted pages, those pages and their contents will be enhanced once inserted into DOM. Calling any method on dynamically created pages / other than the active page, will result an error.
Every jQuery Mobile widget can be enhanced dynamically:
Listview :
Markup enhancement:
$('#mylist').listview('refresh');
Removing listview elements:
$('#mylist li').eq(0).addClass('ui-screen-hidden');
Enhancement example: http://jsfiddle.net/Gajotres/LrAyE/
Note that the refresh() method only affects new nodes appended to a list. This is done for performance reasons.
One of a listview high-points is a filtering functionality. Unfortunately, for some reason, jQuery Mobile will fail to dynamically add filter option to an existing listview. Fortunately there's a workaround. If possible, remove current listview and add another one with a filer option turned on.
Here's a working example: https://stackoverflow.com/a/15163984/1848600
$(document).on('pagebeforeshow', '#index', function(){
$('<ul>').attr({'id':'test-listview','data-role':'listview', 'data-filter':'true','data-filter-placeholder':'Search...'}).appendTo('#index [data-role="content"]');
$('<li>').append('Audi').appendTo('#test-listview');
$('<li>').append('Mercedes').appendTo('#test-listview');
$('<li>').append('Opel').appendTo('#test-listview');
$('#test-listview').listview().listview('refresh');
});
Button
Markup enhancement:
$('[type="button"]').button();
Enhancement example: http://jsfiddle.net/Gajotres/m4rjZ/
One more thing, you don't need to use a input element to create a button, it can be even done with a basic div, here's an example: http://jsfiddle.net/Gajotres/L9xcN/
Navbar
Markup enhancement:
$('[data-role="navbar"]').navbar();
Enhancement example: http://jsfiddle.net/Gajotres/w4m2B/
Here's a demo how to add dynamic navbar tab: http://jsfiddle.net/Gajotres/V6nHp/
And one more in pagebeforecreate event: http://jsfiddle.net/Gajotres/SJG8W/
Text inputs, Search inputs & Textareas
Markup enhancement:
$('[type="text"]').textinput();
Enhancement example: http://jsfiddle.net/Gajotres/9UQ9k/
Sliders & Flip toggle switch
Markup enhancement:
$('[type="range"]').slider();
Enhancement example: http://jsfiddle.net/Gajotres/caCsf/
Enhancement example during the pagebeforecreate event: http://jsfiddle.net/Gajotres/NwMLP/
Sliders are little bit buggy to dynamically create, read more about it here: https://stackoverflow.com/a/15708562/1848600
Checkbox & Radiobox
Markup enhancement:
$('[type="radio"]').checkboxradio();
or if you want to select/deselect another Radiobox/Checkbox element:
$("input[type='radio']").eq(0).attr("checked",false).checkboxradio("refresh");
or
$("input[type='radio']").eq(0).attr("checked",true).checkboxradio("refresh");
Enhancement example: http://jsfiddle.net/Gajotres/VAG6F/
Select menu
Markup enhancement:
$('select').selectmenu();
Enhancement example: http://jsfiddle.net/Gajotres/dEXac/
Collapsible
Unfortunately collapsible element can't be enhanced through some specific method, so trigger('create') must be used instead.
Enhancement example: http://jsfiddle.net/Gajotres/ck6uK/
Table
Markup enhancement:
$(".selector").table("refresh");
While this is a standard way of table enhancement, at this point I can't make it work. So instead use trigger('create').
Enhancement example: http://jsfiddle.net/Gajotres/Zqy4n/
Panels - New
Panel Markup enhancement:
$('.selector').trigger('pagecreate');
Markup enhancement of content dynamically added to Panel:
$('.selector').trigger('pagecreate');
Example: http://jsfiddle.net/Palestinian/PRC8W/
Enhance a page content:
In case we are generating/rebuilding whole page content it is best to do it all at once and it can be done with this:
$('#index').trigger('create');
Enhancement example: http://jsfiddle.net/Gajotres/426NU/
Enhance a full page content (header, content, footer):
Unfortunately for us trigger('create') can not enhance header and footer markup. In that case we need big guns:
$('#index').trigger('pagecreate');
Enhancement example: http://jsfiddle.net/Gajotres/DGZcr/
This is almost a mystic method because I can't find it in official jQuery Mobile documentation. Still it is easily found in jQuery Mobile bug tracker with a warning not to use it unless it is really really necessary.
Note, .trigger('pagecreate'); can suppose be used only once per page refresh, I found it to be untrue:
http://jsfiddle.net/Gajotres/5rzxJ/
3rd party enhancement plugins
There are several 3rd party enhancement plugins. Some are made as an update to an existing method and some are made to fix broken jQM functionalities.
Button text change
Unfortunately cant found the developer of this plugin. Original SO source: Change button text jquery mobile
(function($) {
/*
* Changes the displayed text for a jquery mobile button.
* Encapsulates the idiosyncracies of how jquery re-arranges the DOM
* to display a button for either an <a> link or <input type="button">
*/
$.fn.changeButtonText = function(newText) {
return this.each(function() {
$this = $(this);
if( $this.is('a') ) {
$('span.ui-btn-text',$this).text(newText);
return;
}
if( $this.is('input') ) {
$this.val(newText);
// go up the tree
var ctx = $this.closest('.ui-btn');
$('span.ui-btn-text',ctx).text(newText);
return;
}
});
};
})(jQuery);
Working example: http://jsfiddle.net/Gajotres/mwB22/
Get correct maximum content height
In case page header and footer has a constant height content div can be easily set to cover full available space with a little css trick:
#content {
padding: 0;
position : absolute !important;
top : 40px !important;
right : 0;
bottom : 40px !important;
left : 0 !important;
}
And here's a working example with Google maps api3 demo: http://jsfiddle.net/Gajotres/7kGdE/
This method can be used to get correct maximum content height, and it must be used with a pageshow event.
function getRealContentHeight() {
var header = $.mobile.activePage.find("div[data-role='header']:visible");
var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
var viewport_height = $(window).height();
var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
content_height -= (content.outerHeight() - content.height());
}
return content_height;
}
And here's a live jsFiddle example: http://jsfiddle.net/Gajotres/nVs9J/
There's one thing to remember. This function will correctly get you maximum available content height and at the same time it can be used to stretch that same content. Unfortunately it cant be used to stretch img to full content height, img tag has an overhead of 3px.
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).one("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.page.prototype.options.keepNative = "select, input";
});
Example: http://jsfiddle.net/Gajotres/gAGtS/
Again initialize it before jquery-mobile.js is initialized (look at the example below).
Markup enhancement problems:
Sometimes when creating a component from scratch (like listview) this error will occur:
cannot call methods on listview prior to initialization
It can be prevented with component initialization prior to markup enhancement, this is how you can fix this:
$('#mylist').listview().listview('refresh');
Markup overrding problems:
If for some reason default jQuery Mobile CSS needs to be changed it must be done with !important override. Without it default css styles can not be changed.
Example:
#navbar li {
background: red !important;
}
jsFiddle example: http://jsfiddle.net/Gajotres/vTBGa/
Changes:
01.02.2013 - Added a dynamic navbar demo
01.03.2013 - Added comment about how to dynamically add filtering to a listview
07.03.2013 - Added new chapter: Get correct maximum content height
17.03.2013 - Added few words to the chapter: Get correct maximum content height
29.03.2013 - Added new content about dynamically created sliders and fix an example bug
03.04.2013 - Added new content about dynamically created collapsible elements
04.04.2013 - Added 3rd party plugins chapter
20.05.2013 - Added Dynamically added Panels and contents
21.05.2013 - Added another way of setting full content height
20.06.2013 - Added new chapter: Markup overrding problems
29.06.2013 - Added an important note of WHEN to use enhancement methods
From JQMobile 1.4 you can do .enhanceWithin() on all the children http://api.jquerymobile.com/enhanceWithin/
var content = '<p>Hi</p>';
$('#somediv').html(content);
$('#somediv').enhanceWithin();
I'm using the following theme for our site: http://themes.vivantdesigns.com/vpad/#dashboard.html
I want an ajax loader to show NEXT to the link/tab, when a user clicks a link within the drilldown menu on the left. As you can see from the link, content is dynamically loaded within a:
<section id="main-section">Pagename.html loaded here</section>
So basically, I want the ajax loader to show to the right of the menu links and disappear when the dynamic content loads. It will be hard to see this pause on the demo link, but heavier database queries will cause it to sit there a moment, and slower connections of course.
Any immediate help is appreciated very much.
I've tried show/hide onClick methods, hiding class on document ready, and nothing seems to work cleanly.
Okay, after a lot of screwing around trying to find where the ajax was happening, I think I've worked it out (little familiarity with jQuery/never heard of hashchange or bbq before), so give this a shot.
Assuming you have access to it, the page you referenced is including a JavaScript file called global.js.
Add an initially hidden "loading" image/div/whatever next to each menu item, with an id set similarly to the menu item's name e.g. id="mediaLoading".
Open global.js and head down to line 117:
$('#'+id).length && $('#'+id).remove();
After this line the ajax call is made, so add the code to show the ajax loader, e.g.
var loaderId = h.replace(/^\#/, "") + "Loading";
document.getElementById(loaderId).style.display = 'block';
//or $("#" + loaderId).show() or whatever you would use in jQuery
Finally, to re-hide it, add similar code into the inline 'complete' function (which would now be around line 127):
complete: function(jqXHR, textStatus) {
document.getElementById(loaderId).style.display = 'none';
}
Hope that solves it. It was difficult to test locally.
Keep in mind that since the file's called "global," that obviously might impact a bunch of other pages, so you may want to use null-checks for the loader or a separate file...
I have an app built using jQuery (and using various jQuery-UI tools).
For some reason, i have to port it to smartphones/tablet computer, and decided to use jQuery Mobile for that (in order to minimize the number of changes).
In my vanilla app, I created some elements of the page on the fly, depending of user interactions.
For example a slider could be created like that (p is an object with a bunch of params):
function createSlider(p){
return $("<div/>",{
"id":p.id,
"class":p.divClass,
}).slider({
"orientation": p.align,
"min":p.constraint.min,
"max":p.constraint.max,
"step":p.step,
"value":p.curVal,
"animate":"normal"
/*and some event handling here, but it doesn't matter*/
});
}
And it will produce a nice looking slider. Now it looks like:
function createSlider(p){
return $("<range/>",{
"id":p.id,
"class":p.divClass,
"min":p.constraint.min,
"max":p.constraint.max,
"step":p.step,
"value":p.curVal,
});
}
But as it's created on the fly, all the stuff done by jQuery Mobile on the page load isn't done on it.
Is there a way to force that initialization without writing the slider in the html?
Thanks.
EDIT: I found in the doc that it could be achieved using container.trigger("create");
However this does not work yet.
EDIT2: Ok create was the solution.
According to the documentation (see edit in the question), using trigger("create") on the containing element works.
And to make that work, you also need to remember that range is an input type and not a tag...
Working solution:
function createSlider(){
return $("<input/>",{
"type":"range",
"id":"sl",
"min":0,
"max":15,
"step":1,
"value":1,
});
}
function appendSlider(){
$("#yourdiv").append(createSlider()).trigger("create");
}
As a sidenote, the documentation for jQuery mobile lacks a search option.
Try calling .page() on the container the content is being added to. Alternatively, adding .page() to the content you're returning may also work.