jstree: differentiate between left/middle mouse click - javascript

The following code sets up my tree (the s:property tags are struts2 stuff):
$(function () {
$("#networkTree").jstree({
"json_data" : {
"ajax" : {
"url" : "<s:property value='networkTreeDataUrl'/>"
}
},
"plugins" : [ "themes", "json_data", "ui" ],
"themes" : {
"theme" : "default",
"dots" : true,
"icons" : false
},
"core" : {
"html_titles" : true
}
}).bind("select_node.jstree", function (event, data) {
window.location.href = "<s:property value='companyDetailsUrl'/>" + "?companyId=" + data.rslt.obj.attr("id");
})
});
When the user left clicks a tree item the window URL changes depending on the companyDetailsUrl. So far correct but I'd like the browser (chrome) to open the link in a new tab when I click the middle mouse button as usual. It seems any mouse click selects the tree node and this triggers the bound event which replaces the window.location. What's the best way to prevent this?

I'd go for the which-property of the eventhandler.
This provides an easy way to distinguish buttons, according the jQuery-documentation:
event.which also normalizes button presses (mousedown and mouseupevents), reporting 1 for left button, 2 for middle, and 3 for right.
//rest of the code omitted
.bind("select_node.jstree", function (event, data) {
if(event.which == 1) {
//open link in current window
window.location.href = YOURURL;
} else if (event.which == 3) {
//open link in new window
window.open(YOURURL, '_blank');
}
})
Note that you have to replace YOURURL (obviously). I omitted it for readability.
Further note that this will most likely open a new window, instead of a new tab. For further reading on why it opens a new window and how you can open a new tab I recommend reading this question.

Related

React-router unintended reload on transitionTo (Chrome)

In a (single-page) application implemented on top of React and React Router, we are observing a strange pattern when using the router.transitionTo method.
Apologies for the extra verbose context, but don't want to miss something pertinent.
Let's assume that we have the following Router initialization, which is called from the single "physical" page of the application:
define([], function () {
var _Root = React.createClass({
render : function () {
return React.createElement(React.addons.CSSTransitionGroup, {/**/},
React.createElement(Router.RouteHandler, {/**/}));
}
});
var _NotFoundScreen = React.createClass({/**/});
var _NoDefaultScreen = React.createClass({/**/});
var routes = (
React.createElement(Router.Route, {
handler : _Root,
path : "/SampleApplication/"
},
React.createElement(Router.Route, {
path : "Transfer",
handler : Transfer
}),
React.createElement(Router.Route, {
path : "Home",
handler : Home
}),
React.createElement(Router.DefaultRoute, {
handler : Home || _NoDefaultScreen
}),
React.createElement(Router.NotFoundRoute, {
handler : _NotFoundScreen
})));
return {
init : function () {
var router = Router.create({
routes : routes,
location : Router.HistoryLocation
});
router.run(function (rootClass, state) {
if (state.routes.length === 0) {
window.location = state.path;
}
React.render(React.createElement(rootClass, state), document.getElementById("reactContainer"));
});
}
}
});
And then we have the "Transfer" page with something along the lines of:
define([], function () {
var View = (function (_super) {
/*(...)*/
function View() {
/*(...)*/
}
View.prototype.render = function () {
/*(...)*/
return React.DOM.div(null, React.createElement(Button.Button, {
enabled : true,
onClick : function () {
router.transitionTo("/SampleApplication/Home");
},
style : "btn",
visible : true
}, "B1"), React.DOM.br(), "form:", React.createElement(Form.Form, {
style : "form",
visible : true
}, React.createElement(Button.Button, {
enabled : true,
onClick : function () {
router.transitionTo("/SampleApplication/Home");
},
style : "btn btn-primary",
visible : true
}, "B2")));
};
return View;
})(/*(...)*/);
return View;
});
So, we have 2 buttons on the Transfer page - B1 and B2. B2 is wrapped by a "form" element. Both buttons are capable of "navigating" to the home page, when clicked.
Navigation through B1 works as expected.
Navigation through B2 reveals some peculiar behavior.
browser url: host/SampleApplication/Transfer
we click B2
we "navigate" to host/SampleApplication/Home and see the page content for a fraction of a second
fraction of a second later, browser url changes to host/SampleApplication/Home?
we get a white screen (as if we're loading/accessing the application for the first time and it is initializing)
we get the rendered page # host/SampleApplication/Home?
I have been trying to find the issue for a while now and no amount of debugging seems to be producing any results.
The execution flows for the navigation from both B1 and B2 are identical (down to the point where the React Router calls location.push(path)).
Furthermore, this "only" happens with Chrome (desktop and mobile), Opera (mobile) and Android stock browser, while for Firefox (desktop and mobile) both B1 and B2 are able to navigate from one page to another without any extra reloads nor "leaving" the single physical page of the application.
I have been unable to find any pertinent information about similar behavior patterns that could explain what could be going on.
If anyone could provide some insight on what could be happening here, it would be most appreciated.
With best regards,
SYG
Ok, the source of the problem was identified as being the default type of button element - submit (link to the HTML recommendation).
Since the button was being rendered within a form element, the "onClick" of the button was implicitly submitting the form, causing a page reload to get queued. The "onClick" of the button executes router.transitionTo, effectively navigating to the target page and the "queued" page reload from the form submit gets executed immediately afterwards, causing the application to re-initialize.
The behavior was "fixed" by changing the type of the button element to button.

Allow infinitescroll.js to run X times, then load more posts

I'm using the infinitescroll.js script and it works really well. I've found out how to replace the default functionality with a load more button, using this code:
$(window).unbind('.infscr');
$('.js-next-reports').click(function() {
$grid.infinitescroll('retrieve');
return false;
});
$(document).ajaxError(function(e, xhr, opt) {
if (xhr.status == 404) $('.js-next-reports').remove();
});
However, what I'd like to do is allow infinite scroll to run 3/4 times and then show the .js-next-reports button. I'm not sure how to keep track of how many times infinite scroll has run though. I know there is a currPage var but using console.log I can't work out how I can reference it.
There is also a maxPage option for infinitescroll, which limits it to run only X times, so I could maybe tap into that somehow? I'm not sure how to get a console.log of the options though. Here is my init code if that helps ($grid is just a ref to a div)
$grid.infinitescroll({
// selector for the paged navigation (it will be hidden)
navSelector : ".pagination",
// selector for the NEXT link (to page 2)
nextSelector : ".pagination .next",
// selector for all items you'll retrieve
itemSelector : ".infinite-scroll-post",
contentSelector : "#infinite-scrollable",
debug: true,
// finished message
loading: {
img: "ajax-loader.gif",
msgText: "Loading more projects...",
finishedMsg: 'No more pages to load.',
}
},
});
Maybe something like: ?
if ( .currPage == "3" ) {
$(window).unbind('.infscr');
$('.js-next-reports').click(function() {
$grid.infinitescroll('retrieve');
return false;
});
$(document).ajaxError(function(e, xhr, opt) {
if (xhr.status == 404) $('.js-next-reports').remove();
});
}
But I don't know how to either count the scrolls or access currPage.
Thanks
A JSFiddle would help testing the code, but from what I've read on their documentation, there's a callback that allows you to access currPage inside the state object. Your code should look something like this:
$grid.infinitescroll({
// selector for the paged navigation (it will be hidden)
navSelector : ".pagination",
// selector for the NEXT link (to page 2)
nextSelector : ".pagination .next",
// selector for all items you'll retrieve
itemSelector : ".infinite-scroll-post",
contentSelector : "#infinite-scrollable",
debug: true,
// finished message
loading: {
img: "ajax-loader.gif",
msgText: "Loading more projects...",
finishedMsg: 'No more pages to load.',
},
appendCallback: false
}, function(newitems, opts) {
if(opts.state.currPage == 3) {
$(window).unbind('.infscr');
}
}
});

Ext.window override destroy in child class on close button of window in parent class

I have a ext.window in my code which has the default save and close button. On close button click I am hiding the window:
Ext.define('MyPack.template.TemplateWindow', {
extend : 'Ext.Window',
id: 'templateEditorWindow',
closeAction: 'hide',
autoScroll: false,
createTemplateEditor : function() {
// some code
},
initComponent : function() {
this.createTemplateEditor();
Ext.applyIf(this, {
layout : 'border',
modal : true
});
this.items = [ this.templateEditor ];
this.buttons = [
{ text : '#{msgs.button_save}',
window : this,
handler : function () {
if(this.window.templateEditor.save()) {
this.window.hide();
}
}
},
{ text : '#{msgs.button_close}',
cls : 'secondaryBtn',
window : this,
handler : function( ){
this.window.hide();
}
}
];
this.callParent(arguments);
},
});
I have one another window which is extending above window.
Ext.define('MyPack.template.RestfulTemplateWindow', {
extend : 'MyPack.template.TemplateWindow',
createTemplateEditor : function() {
// some code
}
});
I am creating this child class. The window is created properly. But I want to override handler function of close button. On close it should destroy.
How can I override it?
You can define a closeAction on a window
closeAction : String The action to take when the close header tool is
clicked:
destroy :
remove the window from the DOM and destroy it and all descendant
Components. The window will not be available to be redisplayed via the
show method.
hide :
hide the window by setting visibility to hidden and applying negative
offsets. The window will be available to be redisplayed via the show
method. Note: This behavior has changed! setting does affect the close
method which will invoke the approriate closeAction.
Defaults to: 'destroy'
So there is no need to override anything.
Edit >> Remember to call close() not hide()!
{
text : '#{msgs.button_save}',
window : this,
handler : function () {
if(this.window.templateEditor.save()) {
this.window.close(); // call close!
}
}
},
{ text : '#{msgs.button_close}',
cls : 'secondaryBtn',
window : this,
handler : function( ){
this.window.close(); // call close!
}
}
Edit
Disclaimer: the following way is just a workaround
Ext.define('MyPack.template.RestfulTemplateWindow', {
extend : 'MyPack.template.TemplateWindow',
closeAction: 'destroy', // redefine th close action
initComponent: function() {
// all values set would be overrided by the parent
this.callParent(arguments);
// identify the buttons somehow
this.on('beforehide',function(w){w.close();return false;},this);
}
});

A working method to open a webpage in new window?

I have been trying to write a code in sencha touch, which has a button and when i click on that , it should open a webpage as a pop-up in a new window .
Window.open()-I cannot use this method because it doesn't work fine
in phones.Though I realise this is the easiest way to open a new
browser window.
document.location.href=url - This method opens the URL in the same
page , but I want it to be opened in a new window as pop-up.
Is there any other way to open a page in a new window when a user clicks a button, Below is my code
Ext.application({
name: 'Opening new page',
launch: function() {
Ext.create("Ext.tab.Panel", {
fullscreen: false,
items: [
{
xtype: 'button',
text: 'click to open google',
ui: 'confirm',
handler: function() {
document.location.href=("http://www.google.com/");
}
}
]
});
}
});
Please try this code:
handler: function() {
var link = Ext.getDom('hidden_link');
link.href = 'http://www.google.com'/;
var clickevent = document.createEvent('Event');
clickevent.initEvent('click', true, false);
link.dispatchEvent(clickevent);
}
I don't know exactly how to do it in Ext.js, but I was basically thinking along the same lines as #bunlong-van. Create a anchor tag that targets a new window, add it to the page, and then click it.
This is how it could be done in jQuery:
$('button').bind('click',function(e){
var $me = $(this);
e.preventDefault();
e.stopPropagation();
$('<a />')
.attr('href', $me.data('href'))
.attr('target', '_blank')
.css({display:'none'})
.appendTo($('body'))
.get(0).click();
});
Full Sample: http://jsbin.com/adakur/edit
Hey #coding you can that is a Overlay is a type pop-up, try this into handler event,
var overlay = new Ext.Panel({
floating : true,
modal : true,
centered : true,
width : 500,
height : 500,
styleHtmlContent : true,
html: '<div><iframe style="width:100%;height:100%;" src="http://www.sencha.com/products/touch">Your device does not support iframes.</iframe></div>',
}).show('pop', true)
And please use your brain, I do not I can be doing your homework. I hope this helps. :) Ciao
Use window.open() in your handler as mentioned below:
handler: function() {
window.open("http://www.google.com/", "_blank");
}
Create a pop up window(a simple window) in your working page and make its visibility to false.. when you click on the button, change its visibility to true and give the focus to it..
also you can open anything in that popup window..
or you can use this jQuery code
$(document).ready(function() { tb_show(title, "testpage.aspx?id=" + url + "&TB_iframe=true&width=700&height=600", null); });
in this you can pass the parameters you want. this will open as a new popup window.

TinyMCE add item to context menu

I want to add a new menu item to TinyMCE's context menu, and perform a command when the user clicks it, so far i have this, which is not working:
tinyMCE.init({
...
setup : function(ed) {
ed.onContextMenu.add(function(ed, menu) {
menu.add({title : 'Menu 1', onclick : function() {
alert('Item 1 was clicked.');
}});
});
}
The code above throws an error saying "menu.add is not a function", if i remove the menu.add stuff and place a console.log(menu), it returns "contextmenu" upon opening the context menu.
What would be the right way to add an item to the context menu ? Preferably without having to modify the plugin itself. Thanks in advance.
You will need something like
ed.onContextMenu.add(function(ed, e) {
if (!e.ctrlKey) {
// Restore the last selection since it was removed
if (lastRng)
ed.selection.setRng(lastRng);
var menu = this._getMenu(ed);
if ((typeof menu).toLowerCase() == 'object')
{
menu.showMenu(e.clientX, e.clientY);
Event.add(ed.getDoc(), 'click', function(e) {
hide(ed, e);
});
Event.cancel(e);
}
}
});
and the function _getMenu where you may insert contextmenu options:
//example this will only display if an image was clicked
if (node !== "undefined" && node.nodeName.toLowerCase() == 'img') {
m.add({
title: 'my menu',
});
m.addSeparator();
// Inline-Element editieren
m.add({
title: 'to be choosen1',
icon: 'http://...',
cmd: 'undo'
});
t.onContextMenu.dispatch(t, m, el, col);
return m;
}
EDIT:
you can get the default menu using (the plugin contextmenu needs to be active)
var editor = tinymce.get(editor_id);
var menu = editor.plugins.contextmenu._getMenu(editor);
adding an entry to the menu should work as follows
menu.add({title : 'undo', icon : 'undo', cmd : 'Undo'});
it might be necessary to render the menu explicitly using showMenu.
Another way to insert a menu to the contextemenu is to modify the editor_plugin.js in the tiny_mce/plugins/contextemneu directory and add the entry directly. You may also copy the plugin, modify and rename it - let it work as a custom plugin.
You can add context menu like this:
setup : function(ed) {
ed.onContextMenu.add(function(ed, menu) {
displayContextMenu(ed,e);
}});
});
}
function displayContextMenu(ed,e){
var m = ed.plugins.contextmenu._getMenu(ed);
m.add({title : 'advanced.bold_desc', icon : 'bold', cmd : 'bold'});
}

Categories