After experimenting with a bunch of javascript tabbars (most fail when using forms), i've decided it might be a good idea to go native.
Would anyone know how to incorporate native UIControls (tabbar & header) in a jqTouch app. I'd still need to retain control of the 'back' and 'info' buttons in the header.
Thanks!
Glen
What you need to determine at this point is what is the benefit of the hybrid approach? After you spend all of the time writing the native code to support the navigation and the tabs and the header bar you will have written a fair bit of code.
Then attempting to put that code together in a way to interface back to the Phonegap UIWebview it will, IMHO, become overly complex... however it can be done.
I woud suggest you first write the native application and get it functioning and then integrate that code back in to the PhoneGap Applicate Delegate
Here is a complete tutorial that will be a good starting point
I've worked out the best method to get this working, and thought I'd share the code.
So this is the combo: jQTouch + Phonegap = Native Tabbar that will work in unison with jQTouch. Ie. When you click a tabbar icon, it will take you to the appropriate jQTouch page.
document.addEventListener("deviceready",setupToolbars);
function setupToolbars() {
// Add these if you want the toolbar
// window.uicontrols.createToolBar();
// window.uicontrols.setToolBarTitle("Toolbar");
var activeTab;
activeTab = "#home"; // Better to have intro screen at home, and then make tab1 the first tab.
window.uicontrols.createTabBar();
window.uicontrols.createTabBarItem("tab1", "Tab1", "/www/images/tabs/yourimage1.png", {
onSelect: function() {
myName = "#home"
if (activeTab != myName)
{
jQT.goTo("#home", "fade");
activeTab = myName;
}
}
});
window.uicontrols.createTabBarItem("tab2", "Tab2", "/www/images/tabs/yourimage2.png", {
onSelect: function() {
myName = "#tab2"
if (activeTab != myName)
{
jQT.goTo("#tab2", "fade");
activeTab = myName;
}
}
});
window.uicontrols.createTabBarItem("tab3", "Tab3", "/www/images/tabs/yourimage3.png", {
onSelect: function() {
myName = "#tab3"
if (activeTab != myName)
{
jQT.goTo("#tab3", "fade");
activeTab = myName;
}
}
});
window.uicontrols.createTabBarItem("tab4", "Tab4", "/www/images/tabs/yourimage4.png", {
onSelect: function() {
myName = "#tab4"
if (activeTab != myName)
{
jQT.goTo("#tab4", "fade");
activeTab = myName;
}
}
});
window.uicontrols.showTabBar();
window.uicontrols.showTabBarItems("tab1", "tab2", "tab3", "tab4");
}
Related
I am attempting to disable future dates on a jQuery datepicker being utilized with Tabulator but to no avail.
var table = new Tabulator("#MyDiv", {
height: "100%",
layout: "fitDataFill",
columns: [
{ title: "Date Worked", field: "DateComp", hozAlign: "center", sorter: "date", editor: dateEditor },
{ title: "Memo", field: "Memo", width: 144, hozAlign: "left", editor: "input" },
]
});
var dateEditor = function (cell, onRendered, success, cancel) {
var cellValue = moment(cell.getValue(), "MM/DD/YYYY").format("YYYY-MM-DD");
input = document.createElement("input");
input.setAttribute("type", "date");
input.style.padding = "4px";
input.style.width = "100%";
input.style.boxSizing = "border-box";
input.value = cellValue;
onRendered(function () {
input.style.height = "100%";
//$(input).datepicker({ endDate: new Date() });
$(input).datepicker({ maxDate: 0 });
input.focus();
});
function onChange() {
if (input.value != cellValue) {
success(moment(input.value, "YYYY-MM-DD").format("MM/DD/YYYY"));
} else {
cancel();
}
};
//submit new value on blur or change
input.addEventListener("blur", onChange);
//submit new value on enter
input.addEventListener("keydown", function (e) {
if (e.keyCode == 13) {
onChange();
}
if (e.keyCode == 27) {
cancel();
}
});
return input;
};
I have attempted a couple of fixes by tweaking the datepicker options list (e.g. maxDate and endDate) but nothing seems to work. The future dates on the datepicker are selectable regardless. Is this a Tabulator issue? Or, a jQuery issue?
I have found similar questions regarding use of the jQuery datepicker on other forums and the recommended solutions always seem to revolve around use of the maxDate and endDate options.
Any assistance is greatly appreciated.
It looks like there is an issue using the datepicker inside of the cell, that I couldn't figure out. An error is thrown about the instance data missing.
Here is an example using flatpickr instead of the jQuery datepicker.
https://jsfiddle.net/nrayburn/65t1dp23/49/
The two most important parts are including a validator, so that users cannot type in a date. (I don't think they ever could, but if somehow they do it will prevent invalid dates.). The other is using the maxDate or equivalent parameter from the date picking library when you create the date picker instance.
Here is a custom validator to prevent any dates in the future. (It may not handle time differences properly in this setup.)
function noFutureDate(cell, value){
const cellValue = moment(new Date(value));
const today = moment();
if (cellValue.diff(today) > 0){
return false;
}
return true;
}
You also have to create a custom editor. Here is what you specifically need for the date picker instance. You can get the rest from the fiddle, but the other parts aren't really related to a date picker specifically.
const input = document.createElement("input");
input.value = cell.getValue();
onRendered(function(){
flatpickr(input, {
maxDate: moment().format('MM/DD/YYYY')
})
input.focus();
});
Is there a way to get the paper for an element by referencing the element?
I'm creating elements in a loop and with each element i'm creating a new Raphael(...). See sample below.
Basically I want to stop the animation on click, but paper is undefined and calling stop() on the element itself doesn't work either.
$.each(el,function(key,value)
{
var li = $("<li>",{id:"item"+key).appendTo("#myUl");
var ppr = new Raphael($("item"+key),get(0),48,48);
//... do stuff like animate ...
li.click(function()
{
console.log($(this).paper); //undefined
})
})
I was wondering about a closure like below to capture the paper, so when the anonymous func runs, it has the variable captured.
Note, I'm not sure this is the best method overall, something feels a bit clunky about creating a new paper each time, but just trying to address the specific issue.
Untested code, but if you can get it on a fiddle, I think it should be possible to sort.
$.each(el,function(key,value)
{
var li = $("<li>",{id:"item"+key).appendTo("#myUl");
var ppr = new Raphael($("item"+key),get(0),48,48);
(function() {
var myPaper = ppr;
li.click(function()
{
console.log(myPaper);
})
})();
})
You can also attach the paper to the element's "data" using https://api.jquery.com/data/
$.each(el,function(key,value)
{
var li = $("<li>",{id:"item"+key).appendTo("#myUl");
var ppr = new Raphael($("item"+key),get(0),48,48);
li.data("paper", ppr ); // SAVE
li.click(function()
{
console.log($(this).data("paper")); // LOAD
})
})
i want to show/hide my raphael svg graph with a button click event
please someone who know how to do this. please help me
i try to do by this way but it's not working.
var p = Raphael(900,70,200,200);
p.circle(20,20,20);
$n("#shide").click(function(){
p.hide();
});
please someone who know how to do this. please help me.
Thanks in advance.
You'd better use the return value of drawing functions.
var element1 = p.circle(20,20,20);
var element2 = p.circle(99,99,20);
$n("#shide").click(function(){
element1.hide();
// element2.hide();
});
Also I have some advanced skills about this kind of problem. These skills will be very usefull when you draw your circles or other things with the ajax response data.
function drawCircle() {
var elementObj = {};
$.ajax({url: '', dataType: 'json', method: 'post', data: yourData, success: function (data) {
elementObj['circle1'] = p.circle(20,20,20);
elementObj['circle2'] = p.circle(99,99,20);
});
return elementObj;
}
Then you call this function like this:
var ele = drawCircle();
var hoverInCb = function () {
ele['circle1'] && ele['circle1'].show();
ele['circle2'] && ele['circle2'].show();
};
var hoverOutCb = function () {
ele['circle1'] && ele['circle1'].hide();
ele['circle2'] && ele['circle2'].hide();
};
These code will work because that the returned elementObj is a 'link' of the object. After the data fetched by ajax request, the elementObj will be filled with data, and the ele variable outside there will also get the new data.
Like this:
var paper = Raphael(10, 50, 320, 200);
paper.circle(10, 10, 10, 10)
.attr({fill: "#000"})
.click(function () {
this.hide();
});
I was wondering if there was a way to set a custom Authors category in a Gtk::AboutDialog class via gtkmm. I know there are the following methods:
set_artists()
set_authors()
set_documenters()
set_translator_credits()
But I wanted to add a custom category. Right now I have a program that accepts a bunch of plugins, so on startup when it scans for plugins I would like to populate a "Plugins" page on the about screen once you click credits that shows all of the plugin authors' names (removing duplicates of course). The logic is already there, but it looks quite odd adding them to the artists or documenters categories where they certainly do not belong.
Is there an easy way to add a new category besides rolling my own?
Nice question! In GTK 3, this is fairly easy. You have to do some manipulation of the About dialog's internal children, which may change in future releases, so be warned!
I've written a quick-n-dirty example in Vala that does what you want. That was faster for me because I almost never use Gtkmm. It shouldn't be too hard to translate though.
using Gtk;
int main(string[] args)
{
Gtk.init(ref args);
var dialog = new AboutDialog();
// Fetch internal children, using trickery
var box = dialog.get_child() as Box;
Box? box2 = null;
ButtonBox? buttons = null;
Notebook? notebook = null;
box.forall( (child) => {
if(child.name == "GtkBox")
box2 = child as Box;
else if(child.name == "GtkButtonBox")
buttons = child as ButtonBox;
});
box2.forall( (child) => {
if(child.name == "GtkNotebook")
notebook = child as Notebook;
});
// Add a new page to the notebook (put whatever widgets you want in it)
var plugin_page_index = notebook.append_page(new Label("Plugin 1\nPlugin 2"),
new Label("Plugins"));
// Add a button that toggles whether the page is visible
var button = new ToggleButton.with_label("Plugins");
button.clicked.connect( (button) => {
notebook.page = (button as ToggleButton).active? plugin_page_index : 0;
});
buttons.pack_start(button);
buttons.set_child_secondary(button, true);
// Set some other parameters
dialog.program_name = "Test Program";
dialog.logo_icon_name = Gtk.Stock.ABOUT;
dialog.version = "0.1";
dialog.authors = { "Author 1", "Author 2" };
dialog.show_all(); // otherwise the new widgets are invisible
dialog.run();
return 0;
}
In GTK 2, this is much more difficult, although probably not impossible. You have to connect to the Credits button's clicked signal, with a handler that runs after the normal handler, and then get a list of toplevel windows and look for the new window that opens. Then you can add another page to that window's GtkNotebook.
I would suggest doing it a little differently: add a Plugins button to the action area which opens its own window. Then you don't have to go messing around with internal children. Here's another Vala sample:
using Gtk;
class PluginsAboutDialog : AboutDialog {
private Dialog _plugins_window;
private Widget _plugins_widget;
public Widget plugins_widget { get {
return _plugins_widget;
}
set {
var content_area = _plugins_window.get_content_area() as VBox;
if(_plugins_widget != null)
content_area.remove(_plugins_widget);
_plugins_widget = value;
content_area.pack_start(value);
}}
public PluginsAboutDialog() {
_plugins_window = new Dialog();
_plugins_window.title = "Plugins";
_plugins_window.add_buttons(Stock.CLOSE, ResponseType.CLOSE, null);
_plugins_window.response.connect((widget, response) => { widget.hide(); });
var buttons = get_action_area() as HButtonBox;
// Add a button that opens a plugins window
var button = new Button.with_label("Plugins");
button.clicked.connect( (button) => {
_plugins_window.show_all();
_plugins_window.run();
});
button.show();
buttons.pack_start(button);
buttons.set_child_secondary(button, true);
}
public static int main(string[] args) {
Gtk.init(ref args);
var dialog = new PluginsAboutDialog();
// Make a widget for the plugins window
var can_be_any_widget = new Label("Plugin 1\nPlugin 2");
dialog.plugins_widget = can_be_any_widget;
// Set some other parameters
dialog.program_name = "Test Program";
dialog.logo_icon_name = Gtk.Stock.ABOUT;
dialog.version = "0.1";
dialog.authors = { "Author 1", "Author 2" };
dialog.run();
return 0;
}
}
Just asked a question on regular expression here, basically we need to give an option to people to select some part of text which will be hidden with a MORE button on flash front end, and when some one will click on MORE it will expand it. here is sample text in tinyMCE
some text <start> some inner test </end>
so here is the regular expression to catch this start and end text,
<start>(((?!<(?:\/end|start)>).)+)<\/end>
the above expression will be used to strip this SOME INNER TEST and we will convert this to FLASH friendly MORE button.
My question is, Is there any way to highlight the text inside start & end tags on the fly (while editing) so people will know which part will be hidden for MORE button
Okay guys pat my shoulder on this :D If you don't know what are the code below then learn the basic of TinyMCE initializing. I have done this on jQuery version.
Here is my solution
var highlighter = 1; // A global variable, just to create a toggle for show/hide highlight
added three custom buttons
theme_advanced_buttons1: 'startmore, highlight, endmore, ...';
add setup: to initializing code.
// start highlight, end highlight and show highlight buttons
setup: function(ed) {
ed.addButton('startmore', {
title: 'Start More',
image: 'images/end_s.png',
onclick: function() {
ed.selection.setContent('[start]');
}
});
ed.addButton('endmore', {
title: 'End More',
image: 'images/end_m.png',
onclick: function() {
ed.selection.setContent('[end]');
if (1 == highlighter) {
highlight_tags();
}
}
});
ed.onInit.add(function(ed) {
highlight_tags();
});
ed.onSubmit.add(function(ed, e) {
var html_output = highlight_remove(tinyMCE.activeEditor.getContent());
tinyMCE.activeEditor.setContent(html_output);
});
ed.addButton('highlight', {
title: 'Show collapse selection',
image: 'images/end_highlight.png',
onclick: function() {
if (1 == highlighter) {
var html_output = highlight_remove(tinyMCE.activeEditor.getContent());
tinyMCE.activeEditor.setContent(html_output);
highlighter = 0;
} else {
highlight_tags();
highlighter = 1;
}
}
});
ed.onContextMenu.add(function(ed, e) {
tinymce.dom.Event.cancel(e);
if (1 == highlighter) {
highlight_tags();
}
});
}
onContextMenu is used to show / fix the highlight by right-clicking inside the editor.
There are issue to show highlight on they fly as as soon I setSontent() it moves the cursor at the start of first line.
Below are the regular expression functions to put the highlight around the [start][end] tags.
function highlight_tags() {
var html_output = tinyMCE.activeEditor.getContent();
html_output = highlight_remove(html_output);
var regex = new RegExp(/\[start\](((?!\[(?:end|start)\]).)+)\[end\]/ig);
html_output = html_output.replace(regex,'<span style="background-color:> yellow;">[start]$1[end]</span>');
tinyMCE.activeEditor.setContent(html_output);
}
function highlight_remove(html_output) {
var regex_fix = new RegExp(/<span\sstyle="background-color:\syellow;">(.+?)<\/span>/ig);
return html_output.replace(regex_fix,'$1');
}
Hmm so far it is serving me.
Just onSubmit I am trying to remove the highlight so it wont go in database and for a second I can see that highlight is removed. But it goes in database... so fixing this now.
Let me know if you guys didn't understand any part.
NOTE: If there is any typo in code that might be this stack overflow editor :).
NOTE: I know this code can be improved a lot, so enlighten me please.