Comments (18)
There's a new vex2 project which removes the jQuery dependency. Take note though, the project is very new and there are some known bugs and backwards-compatibility issues still to address.
https://github.com/bbatliner/vex2
https://github.com/bbatliner/vex2-dialog/issues
from vex.
@bbatliner that all sounds good to me. Thanks so much for working on this. I think the community will benefit greatly from the improvements and changes your talking about.
from vex.
I wonder why @bbatliner elected to not make that a PR, I think removing jQuery would be great for this project.
from vex.
It's more of a rewrite than a one-issue fix. vex2
has other notable
changes:
- written in JavaScript instead of CoffeeScript
- modular plugin-system
I'm also suggesting that as long as the module is new that vex2
make a
breaking change to make the use "secure by default" by treating the
"messages" passed through as strings rather than raw HTML. HTML could still
be used if it was passed through a new 'unsafeMessageproperty, which would a clue to the developer or QA person that the string needs to be escaped. This change really only applies to the
dialog` plugin, not the
core. I've published a fork of the plugin that works like that:
https://github.com/RideAmigosCorp/vex2-safe-dialog
The vex dialog plugin claimed to a "drop in replacement" for the standard
alert
, confirm
and prompt
messages, but vex made a major change from
the built-ins as far as security is concerned. The original methods didn't
allow HTML through, but vex does, leaving it up to developers to remember
to always properly escape untrusted values or have XSS vulnerabilities.
XSS holes are unlikely to be noticed unless you are specifically testing
for them in the current design.
However, if vex made HTML escaping the /default/, developers are definitely
going to notice if they intended some HTML to render and got escaped HTML
instead. Then they'll realize they need to use the 'unsafeMessage' property
pass raw HTML through. The property name should then hopefully be enough a
reminder that if raw HTML is going to be passed through, property escaping
or sanitizing untrusted data needs to happen.
Ten years ago HTML templating engines defaulted to allowing raw HTML
through variables by default.
Templating engines released in the last few years generally switch to the
safer default of HTML-escaping variables.
Related tools like vex would be doing a community service to provide
security protection by default, just the built-ins vex was intended to
replace did.
On Fri, Jul 15, 2016 at 2:54 PM, Zack Bloom [email protected]
wrote:
I wonder why @bbatliner https://github.com/bbatliner elected to not
make that a PR, I think removing jQuery would be great for this project.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#55 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABk5V8LhwpDOuuNGlSJwA5X9dOhyKj8ks5qV9dTgaJpZM4B3vNs
.
Mark Stosberg
Senior Systems Engineer
RideAmigos
from vex.
Hi everyone - I'm the maintainer of vex2. My main goals when rewriting vex were:
- Remove jQuery and try to be dependency-free or as lightweight as possible
- Simplify the library by relying on more "JavaScript-y" patterns like closures, not storing state in the DOM, etc.
- Keep as much backwards compatibility with vex and browser support as possible
I agree with @markstos's safe-by-default approach and would certainly want to incorporate his changes into vex2 before looking to merge back to vex. @adamschwartz I also see talk of moving to a modern build tool (Gulp) and using ES6, which I would be happy to include with vex2 since I've already moved away from CoffeeScript.
My thought is that we can work together to prepare vex2 to be merged back into vex as a PR, as you suggested. Upgrade guides, API docs, and bugfixes/compatibility issues are what's needed to get to that point. What do you think?
from vex.
Woot! We made it - vex2 has been merged upstream. Thanks for the support everyone.
Edit: The latest major version release of vex is currently in beta. Install it with npm i [email protected] vex-dialog
(or download the files from the repo) and check the documentation for breaking changes.
from vex.
Yes please!
from vex.
+1
from vex.
+1
from vex.
+1
from vex.
+1
from vex.
+1
from vex.
I took a crack at using Zepto instead of jQuery. It works for my project, but I probably missed a few things. My general strategy: eliminate serializing the options into vex DOM object "data-vex" attributes, and instead keep them in a global hash object (optionsHash) since core Zepto does not duplicate $.data exactly (there is a plugin for it, but I wanted to avoid that); each vex DOM object instead just keeps track of its vex id.
diff --git a/js/vex.dialog.js b/js/vex.dialog.js
index 6d3b873..dbf3911 100644
--- a/js/vex.dialog.js
+++ b/js/vex.dialog.js
@@ -33,8 +33,10 @@
type: 'button',
className: 'vex-dialog-button-secondary',
click: function($vexContent, event) {
- $vexContent.data().vex.value = false;
- return vex.close($vexContent.data().vex.id);
+ var id = $vexContent.data('vex-id');
+ var options = vex.getOptionsById(id);
+ options.value = false;
+ return vex.close(id);
}
}
};
@@ -52,8 +54,10 @@
$vexContent = $form.parent();
event.preventDefault();
event.stopPropagation();
- $vexContent.data().vex.value = dialog.getFormValueOnSubmit($formToObject($form));
- return vex.close($vexContent.data().vex.id);
+ var id = $vexContent.data('vex-id');
+ var options = vex.getOptionsById(id);
+ options.value = dialog.getFormValueOnSubmit($formToObject($form));
+ return vex.close(id);
},
focusFirstInput: true
};
@@ -147,7 +151,7 @@
} else if (typeof exports === 'object') {
module.exports = vexDialogFactory(require('jquery'), require('./vex.js'));
} else {
- window.vex.dialog = vexDialogFactory(window.jQuery, window.vex);
+ window.vex.dialog = vexDialogFactory(typeof(jQuery)=="undefined" ? Zepto : jQuery, vex);
}
}).call(this);
diff --git a/js/vex.js b/js/vex.js
index 2b3884c..9e6d18f 100644
--- a/js/vex.js
+++ b/js/vex.js
@@ -16,6 +16,7 @@
});
return vex = {
globalID: 1,
+ optionsHash: {},
animationEndEvent: 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend',
baseClassNames: {
vex: 'vex',
@@ -44,30 +45,33 @@
options = $.extend({}, vex.defaultOptions, options);
options.id = vex.globalID;
vex.globalID += 1;
- options.$vex = $('<div>').addClass(vex.baseClassNames.vex).addClass(options.className).css(options.css).data({
- vex: options
- });
- options.$vexOverlay = $('<div>').addClass(vex.baseClassNames.overlay).addClass(options.overlayClassName).css(options.overlayCSS).data({
- vex: options
- });
+ vex.optionsHash[options.id] = options;
+ options.$vex = $('<div>')
+ .addClass(vex.baseClassNames.vex)
+ .addClass(options.className)
+ .css(options.css).data('vex-id',options.id);
+ options.$vexOverlay = $('<div>')
+ .addClass(vex.baseClassNames.overlay)
+ .addClass(options.overlayClassName)
+ .css(options.overlayCSS).data('vex-id',options.id);
if (options.overlayClosesOnClick) {
options.$vexOverlay.bind('click.vex', function(e) {
if (e.target !== this) {
return;
}
- return vex.close($(this).data().vex.id);
+ return vex.close(options.id);
});
}
options.$vex.append(options.$vexOverlay);
- options.$vexContent = $('<div>').addClass(vex.baseClassNames.content).addClass(options.contentClassName).css(options.contentCSS).append(options.content).data({
- vex: options
- });
+ options.$vexContent = $('<div>').addClass(vex.baseClassNames.content).addClass(options.contentClassName).css(options.contentCSS).append(options.content).data(
+ "vex-id", options.id
+ );
options.$vex.append(options.$vexContent);
if (options.showCloseButton) {
- options.$closeButton = $('<div>').addClass(vex.baseClassNames.close).addClass(options.closeClassName).css(options.closeCSS).data({
- vex: options
- }).bind('click.vex', function() {
- return vex.close($(this).data().vex.id);
+ options.$closeButton = $('<div>').addClass(vex.baseClassNames.close).addClass(options.closeClassName).css(options.closeCSS).data(
+ "vex-id", options.id
+ ).bind('click.vex', function() {
+ return vex.close(options.id);
});
options.$vexContent.append(options.$closeButton);
}
@@ -85,11 +89,16 @@
return "." + (baseClass.split(' ').join('.'));
},
getAllVexes: function() {
- return $("." + vex.baseClassNames.vex + ":not(\"." + vex.baseClassNames.closing + "\") " + (vex.getSelectorFromBaseClass(vex.baseClassNames.content)));
+ return $("." + vex.baseClassNames.vex)
+ .not("." + vex.baseClassNames.closing)
+ .not(vex.getSelectorFromBaseClass(vex.baseClassNames.content));
+ },
+ getOptionsById: function(id) {
+ return vex.optionsHash[id];
},
getVexByID: function(id) {
return vex.getAllVexes().filter(function() {
- return $(this).data().vex.id === id;
+ return $(this).data('vex-id') === id;
});
},
close: function(id) {
@@ -99,14 +108,14 @@
if (!$lastVex.length) {
return false;
}
- id = $lastVex.data().vex.id;
+ id = $lastVex.data('vex-id');
}
return vex.closeByID(id);
},
closeAll: function() {
var ids;
ids = vex.getAllVexes().map(function() {
- return $(this).data().vex.id;
+ return $(this).data('vex-id');
}).toArray();
if (!(ids != null ? ids.length : void 0)) {
return false;
@@ -117,19 +126,22 @@
return true;
},
closeByID: function(id) {
- var $vex, $vexContent, beforeClose, close, hasAnimation, options;
+ var options = vex.getOptionsById(id);
+ var $vex, $vexContent, beforeClose, close, hasAnimation;
$vexContent = vex.getVexByID(id);
if (!$vexContent.length) {
return;
}
- $vex = $vexContent.data().vex.$vex;
- options = $.extend({}, $vexContent.data().vex);
+ $vex = $vexContent.closest('.vex');
beforeClose = function() {
if (options.beforeClose) {
return options.beforeClose($vexContent, options);
}
};
close = function() {
+ if (id in vex.optionsHash) {
+ delete vex.optionsHash[id];
+ }
$vexContent.trigger('vexClose', options);
$vex.remove();
$('body').trigger('vexAfterClose', options);
@@ -140,7 +152,7 @@
hasAnimation = $vexContent.css('animationName') !== 'none' && $vexContent.css('animationDuration') !== '0s';
if (animationEndSupport && hasAnimation) {
if (beforeClose() !== false) {
- $vex.unbind(vex.animationEndEvent).bind(vex.animationEndEvent, function() {
+ $vex.off(vex.animationEndEvent).bind(vex.animationEndEvent, function() {
return close();
}).addClass(vex.baseClassNames.closing);
}
@@ -154,14 +166,15 @@
closeByEscape: function() {
var $lastVex, id, ids;
ids = vex.getAllVexes().map(function() {
- return $(this).data().vex.id;
+ return $(this).data('vex-id');
}).toArray();
if (!(ids != null ? ids.length : void 0)) {
return false;
}
id = Math.max.apply(Math, ids);
$lastVex = vex.getVexByID(id);
- if ($lastVex.data().vex.escapeButtonCloses !== true) {
+ var options = vex.getOptionsById(id);
+ if (options.escapeButtonCloses !== true) {
return false;
}
return vex.closeByID(id);
@@ -190,7 +203,7 @@
} else if (typeof exports === 'object') {
module.exports = vexFactory(require('jquery'));
} else {
- window.vex = vexFactory(jQuery);
+ window.vex = vexFactory(typeof(jQuery)=="undefined" ? Zepto : jQuery);
}
}).call(this);
from vex.
@ericlenio I believe you're missing the point of this request.
It's remove jQuery dependency
and not:
It's remove jQuery dependency
😄
from vex.
@tborychowski yeah OK I see what you mean. I made a 2nd attempt to do it in ericlenio@6e93c38. Notes about it:
- this is my first attempt at coffeescript, I am sure I did some things "really ugly"
- only limited testing in Chrome
- I have zero experience with AMD and CommonJS, they are completely untested
- I removed 3 apparently unused methods: showLoading, hideLoading, closeAll
- I was not sure how to properly handle namespaced events, like click.vex, so I just used regular events
- I'm really hoping one of you who knows coffeescript can review this, and ideally it can be merged back to this project
from vex.
The vex2 author did ask for feedback from HubSpot on Twitter, but has
gotten no reply from them in that medium so far:
https://twitter.com/thebatliner/status/752514232646635520
On Fri, Jul 15, 2016 at 3:44 PM, Mark Stosberg [email protected] wrote:
It's more of a rewrite than a one-issue fix.
vex2
has other notable
changes:
- written in JavaScript instead of CoffeeScript
- modular plugin-system
I'm also suggesting that as long as the module is new that
vex2
make a
breaking change to make the use "secure by default" by treating the
"messages" passed through as strings rather than raw HTML. HTML could still
be used if it was passed through a new 'unsafeMessageproperty, which would a clue to the developer or QA person that the string needs to be escaped. This change really only applies to the
dialog` plugin, not the
core. I've published a fork of the plugin that works like that:https://github.com/RideAmigosCorp/vex2-safe-dialog
The vex dialog plugin claimed to a "drop in replacement" for the standard
alert
,confirm
andprompt
messages, but vex made a major change from
the built-ins as far as security is concerned. The original methods didn't
allow HTML through, but vex does, leaving it up to developers to remember
to always properly escape untrusted values or have XSS vulnerabilities.
XSS holes are unlikely to be noticed unless you are specifically testing
for them in the current design.However, if vex made HTML escaping the /default/, developers are
definitely going to notice if they intended some HTML to render and got
escaped HTML instead. Then they'll realize they need to use the
'unsafeMessage' property pass raw HTML through. The property name should
then hopefully be enough a reminder that if raw HTML is going to be passed
through, property escaping or sanitizing untrusted data needs to happen.Ten years ago HTML templating engines defaulted to allowing raw HTML
through variables by default.Templating engines released in the last few years generally switch to the
safer default of HTML-escaping variables.Related tools like vex would be doing a community service to provide
security protection by default, just the built-ins vex was intended to
replace did.On Fri, Jul 15, 2016 at 2:54 PM, Zack Bloom [email protected]
wrote:I wonder why @bbatliner https://github.com/bbatliner elected to not
make that a PR, I think removing jQuery would be great for this project.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#55 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABk5V8LhwpDOuuNGlSJwA5X9dOhyKj8ks5qV9dTgaJpZM4B3vNs
.Mark Stosberg Senior Systems Engineer RideAmigos
Mark Stosberg
Senior Systems Engineer
RideAmigos
from vex.
For the record, I don’t think I’d have a problem accepting most if not all of those changes in a PR. Breaking changes are not a deal breaker. We would just slap a 3.0 and let people know how to update their method calls. The library has to change with best practices, so we should do whatever continues to keep vex as useful/beneficial to the community as possible. That being said, if the authors of vex2 have plans to take vex in a different direction entirely, feel free. But nothing I’ve heard or seen so far suggests it’s too much of a departure to be merged back in, caveats above.
from vex.
Thanks for the reply, @adamschwartz . vex2 author mentioned being busy with work doing the week, so perhaps he can join the conversation this weekend.
from vex.
Related Issues (20)
- HTML entities in unsafeMessage/unsafeContent
- is it possible to open vex over a canvas ?
- Help moving vex and using append location
- vex-open remains on body in chrome if dialog is closed in background with child browser window & print dialog is called (then print cancelled or proceed) HOT 1
- vex input field sanitizes spaces
- Multiple Buttons?
- problem with the modal position and size HOT 1
- how to use it in Vue? HOT 2
- readme spelling error
- file input inside vex.open() HOT 1
- Dynamic select using AngularJS with ng-options
- vex.close could cover submission
- demos in documentation don't work
- button click opens and closes dialog at the same time HOT 2
- Can Vex Modal lock? HOT 1
- Unsafe assignment to innerHTML
- Animations required for close
- Make buttons respond to Enter and Esc keys
- Refresh buttons of a dialog confirm HOT 1
- vex dialog buttons are not working as expected. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vex.