insert xul element into browser so it scrolls with it - firefox-addon

I'm trying to insert an xul element into the gBrowser.selectedBrowser element so that this xul element scrolls with the document node.
I used this code to create and add a box:
var win = Services.wm.getMostRecentWindow('navigator:browser');
var panel = win.document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul','box');
var props = {
style: 'width:300px;height:100px;background-color:red;'
}
for (var p in props) {
panel.setAttribute(p, props[p]);
}
gBrowser.selectedBrowser.appendChild(panel);
problem is that the box is not seen anywhere. it is in the dom inspection though:

As outlined in the comments above the issue is that the <browser> element does not render its contents, similar to an <iframe>.
Your options to have the box scroll with the content are
a) reposition your box via javascript on scroll events
b) build the HTML equivalent of your box and inject it into the content directly. If the page content is untrusted you have to consider security concerns into accounts since it could manipulate the DOM used by your addon.

Related

ASP.Net MVC jQuery UI MultiSelect MultiSelectFilter

I am having a problem with the jQuery multiselect plugin.
Essentially I have a partial view which renders and is hidden when the page is loaded.
Within the partial view I have the following code defined in a script section:
$(document).ready(function () {
$('#ddlCountries').multiselect().multiselectfilter();
var countries = $('#ddlCountries');
var parent = $("#ddlCountries").parent();
var span = $("#ddlCountries").parent().find("span[class='custom-select-back']");
debugger;
This code selects a dropdown list and applies the multiselect plugin - along with the filter options. Everything is fine with one exception - once the partial is displayed a span object with a class of "custom-select-back" is rendered over the top meaning I cannot use the control.
Code used in other parts of the system simply selects the parent of the dropdown and hides the span as can be seen above - Unfortunately in this case that code does not work.
If I inspect the source at the point the debugger is hit the parent of ddlCountries is the parent DIV - the span doesn't exist at this stage.
If I inspect the source after the page has finished loading, the parent is an element custom-select object which now contains the problematic span.
I need to somehow hide this span but I cannot see how or where I can do this. Does anybody have any ideas?
In the end I could not resolve this using jQuery/javascript as DOM elements simply did not exist at the the point the code executed.
I instead used CSS to hide the element (display:none) when it was eventually added.

Select2 change container position

How can I adjust the position of Select2 container so that the search box is position right over the original select element like in this website
http://www.jobnisit.com/en
It look cleaner in terms of UI in my opinion.
Ps. sorry, I can't post the image now.
There is 2 ways to do this.
1) With css:
.select2-dropdown--below {
top: -2.8rem; /*your input height*/
}
This will not affect a container (.select2-container), but will move dropdown and search field, so you will have a desired effect.
2) With js:
$('select').select2().on('select2:open', function() {
var container = .$('.select2-container').last();
/*Add some css-class to container or reposition it*/
});
This code attaches a handler to 'select2:open' event, which will be fired every time when user opens a dropdown. This method is better if you have more than one select on page.
Tested with select2 4.0.0
The proper way of positioning the dropdown is using the core feature provided by select2 plugin.
It provides us with 'dropdownParent' property to place to dropdown inside the particular element
select field: #edit-field-job-skillsets-tid
parent item: div.form-item-field-job-skillsets-tid
jQuery("#edit-field-job-skillsets-tid").select2(
{dropdownParent: jQuery('div.form-item-field-job-skillsets-tid')}
);

Asp.net mvc use Jquery mobile in partial View [duplicate]

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();

jQuery UI: combining Sortable with Draggable while cloning the Sortable

I'm trying to build an interface tool which essentially allows users to build a grid out of common UI elements.
Here's a jsFiddle: http://jsfiddle.net/FX4Fw/
Essentially, the idea is that you drag content elements (picture, headline, standfirst, etc) into the grey placeholder at the bottom. Once they're in there, they should no longer be Draggables (because this breaks the CSS grid system they inherit) and they can then be resized. The original items in the UI should stay where they are, so the user is essentially cloning them into the box to be positioned.
This almost works in my demo, but when the user grabs a UI element and drags it into the placeholder, I then remove the ui-draggable class from the cloned element that ends up inside the placeholder. This also removes it from the original source element (I want this to stay where it is) so it's no longer usable.
Is there a way to combine these things so they work in tandem? Hopefully it's clear what I'm trying to do.
Never mind - found the answer here: https://stackoverflow.com/a/3041887/176615
(basically this code)
stop: function(event, ui) {
//check it wasn't here previously
if(!ui.item.data('tag') && !ui.item.data('handle')) {
ui.item.data('tag', true); //tag new draggable drops
ui.item.removeClass('ui-draggable'); // dirty hack
}
},

slide up remaining items

I am working on a tool based on jQuery UI draggable functionality.
I have a number of boxes in the left column of the table. When they are dragged in yellow area, I would expect the remaining divs to move upwards to fill the space left by the box that was moved.
But it's not happening. Why?
It is pretty difficult to test but from my knowledge on the question here is a possible cause/solution to this.
The droppable plugin does not remove the dragged element from its original markup position, it is visually moved to the droppable element (with some option allowing to accept to drop certain elements or not, events, etc).
The elements have a position: relative css rule, which represents the "normal flow" for elements (in the order they appear in the markup). So even if the element is visually placed elsewhere on the page with css, its place in the markup is still the same and it is still taking the space it normally should.
This fiddle illustrate what i'm trying to explain :-)
By looking at the source code form the "working website", they actually remove the dragged element from the original draggable list and re-create it in the droppable list !
When they define the .droppable() they do this:
h.droppable({
tolerance: "intersect",
accept: ".card",
greedy: true,
drop: function (a, b) {
card = b.draggable;
putCardIntoStack(card, c)
}
});
On the drop event, they call putCardIntoStack(card, c) passing the currently dragged element as the card parameter. Within this method, they remove the original "card" (a.remove()) and re-create it in the dropzone (newcard = createCard();):
function putCardIntoStack(a, b) {
progressVal = $('#progBarRd').width();
card_idDOM = a.attr('id');
card_idDB = card_idDOM.substr(IDPREFIX_CARD.length, card_idDOM.length - IDPREFIX_CARD.length);
stack_idDB = b.substr(IDPREFIX_STACK.length, b.length - IDPREFIX_STACK.length);
$.ajax({
url: URL_DRAGDROPAJAX,
type: 'POST',
data: 'action=movecard&cardid=' + card_idDB + '&tostack=' + stack_idDB + '&prog=' + progressVal
});
// 'a' is the card
// they extract the id/content from the dragged card
cardId = a.attr('id');
cardLabel = a.text();
// they remove the card from the DOM
a.remove();
// they create a new card with the extracted info
newcard = createCard(cardId, cardLabel);
newcard.addClass('stackcard');
// and append it to the dropzone
$('#' + b).removeClass("empty").find('.stackDrop').append(newcard);
globalcheck()
}
jQuery UI does a similar thing on the droppable demo page. On the drop event, they call a function deleteImage() which removes the dragged image from the original markup and appends it to the drop zone.
I hope I'm clear enough :-)
I also hope I'm right, it is pretty difficult to test quickly but it makes sense :-)

Resources