Code Monkey home page Code Monkey logo

Comments (18)

markstos avatar markstos commented on July 24, 2024 3

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.

adamschwartz avatar adamschwartz commented on July 24, 2024 2

@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.

zackbloom avatar zackbloom commented on July 24, 2024 1

I wonder why @bbatliner elected to not make that a PR, I think removing jQuery would be great for this project.

from vex.

markstos avatar markstos commented on July 24, 2024 1

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 thedialog` 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.

bbatliner avatar bbatliner commented on July 24, 2024 1

Hi everyone - I'm the maintainer of vex2. My main goals when rewriting vex were:

  1. Remove jQuery and try to be dependency-free or as lightweight as possible
  2. Simplify the library by relying on more "JavaScript-y" patterns like closures, not storing state in the DOM, etc.
  3. 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.

bbatliner avatar bbatliner commented on July 24, 2024 1

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.

ch3stnut avatar ch3stnut commented on July 24, 2024

Yes please!

from vex.

ngault avatar ngault commented on July 24, 2024

+1

from vex.

hausofwong avatar hausofwong commented on July 24, 2024

+1

from vex.

andylima avatar andylima commented on July 24, 2024

+1

from vex.

mfrye-intuit avatar mfrye-intuit commented on July 24, 2024

+1

from vex.

tborychowski avatar tborychowski commented on July 24, 2024

+1

from vex.

ericlenio avatar ericlenio commented on July 24, 2024

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.

tborychowski avatar tborychowski commented on July 24, 2024

@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.

ericlenio avatar ericlenio commented on July 24, 2024

@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.

markstos avatar markstos commented on July 24, 2024

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 thedialog` 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

Mark Stosberg
Senior Systems Engineer
RideAmigos

from vex.

adamschwartz avatar adamschwartz commented on July 24, 2024

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.

markstos avatar markstos commented on July 24, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.