CssClassApplier - handling dynamic attributes with toggleSelection

114 views
Skip to first unread message

sid...@atelierwalser.at

unread,
Nov 5, 2013, 8:50:07 AM11/5/13
to ra...@googlegroups.com

Hi!

I've got the following function as an EventListener:

var methods = {
addLink: function () {
// create 'search pattern'-object
var classapplier = rangy.createCssClassApplier('link', {elementTagName: 'a', normalize: true});
if(classapplier.isAppliedToSelection()) {
// remove a-tag if it's already set
classapplier.toggleSelection();
} else {
// add a-tag
var link = prompt('Please insert URL.','http://www.example.com/');
if(link) {
classapplier = rangy.createCssClassApplier('link', {elementTagName: 'a', elementProperties: {href: link}, normalize: true});
classapplier.toggleSelection();
}
}
// avoid losing focus
return false;
}
}

$('.toolbar').mousedown(methods.addLink);

For example, if i have the following Text:

Lorem ipsum dolor sit amet, {selectionStart}consetetur sadipscing elitr{selectionEnd}, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

The first click on '.toolbar' results in:

Lorem ipsum dolor sit amet, {selectionStart}<a href="http://www.example.com/" class="link">consetetur sadipscing elitr</a>{selectionEnd}, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

Perfect!

But when i click '.toolbar' for the second time, it results in:

Lorem ipsum dolor sit amet, {selectionStart}<a href="http://www.example.com/" class>consetetur sadipscing elitr</a>{selectionEnd}, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

You see what happened? Only the class 'link' got removed, but the a-tag with its href is still available. 
classapplier.isAppliedToSelection() returned true, like expected. 

Another click on the toolbar, with changed url (e.g. http://www.another-example.com/), results in:

Lorem ipsum dolor sit amet, {selectionStart}<a href="http://www.example.com/" class="link">consetetur sadipscing elitr</a>{selectionEnd}, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

You can see, the class "link" got added again, but the href was not changed to another-example.com.

I'm pretty sure the reason for this issue, is the missing or non-equal href parameter. For tests, i changed the function mentioned above, to the following:

var methods = {
addLink: function () {
var classapplier = rangy.createCssClassApplier('link', {elementTagName: 'a', elementProperties: {href: '#'}, normalize: true});
if(classapplier.isAppliedToSelection()) {
// remove a-tag if it's already set
classapplier.toggleSelection();
} else {
// add a-tag
var link = '#';
if(link) {
classapplier = rangy.createCssClassApplier('link', {elementTagName: 'a', elementProperties: {href: link}, normalize: true});
classapplier.toggleSelection();
}
}
// avoid losing focus
return false;
}
}

Now, the href parameter always has the same contents ('#') and everything's working perfectly.
But in my case, i cannot define a fixed cssClassApplier - because of the dynamic href values.

I wasn't sure if i should submit this as a missing feature to google code - maybe it's my fault ;)

I'm using version 1.2.3 but this also occurs in 1.3alpha.
Tested in Safari and Firefox.

I hope you can understand everything i tried to explain, my english is not the best :P

Thanks in advance!

sid...@atelierwalser.at

unread,
Nov 7, 2013, 9:04:57 AM11/7/13
to ra...@googlegroups.com

Hey, it's me again ...

I found a way doing this by the following (update highlighted green):

var methods = {
addLink: function () {
// create 'search pattern'-object
var classapplier = rangy.createCssClassApplier('link', {elementTagName: 'a', normalize: true});
if(classapplier.isAppliedToSelection()) {
// remove a-tag if it's already set
var randomclass = 'temp' + new Date().getUTCMilliseconds();
classapplier_temp = rangy.createCssClassApplier(randomclass, {normalize: true});
    classapplier_temp.applyToSelection();
var temp = $('.' + randomclass);
    temp.unwrap();
    temp.contents().unwrap();
} else {
// add a-tag
var link = prompt('Please insert URL.','http://www.example.com/');
if(link) {
classapplier = rangy.createCssClassApplier('link', {elementTagName: 'a', elementProperties: {href: link}, normalize: true});
classapplier.toggleSelection();
}
}
// avoid losing focus
return false;
}
}

Not perfect, but it's okay.

Tim Down

unread,
Nov 9, 2013, 1:29:35 PM11/9/13
to rangy
Yes, it is tricky with cases like that. It's right at the edge of what I'd imagined the class applier module being used for. This and other issues have made me wonder about changing the class applier module to use callbacks when considering which elements to add or remove, or indeed make an altogether more flexible style applier module instead (although I've been down that road once and found the task too much for the amount of time I can spend on it), but realistically I'm not going to do that for 1.3.

There is a newish onElementCreate option in 1.3 already that may help. See http://code.google.com/p/rangy/issues/detail?id=143.

Tim


--
You received this message because you are subscribed to the Google Groups "rangy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rangy+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

sid...@atelierwalser.at

unread,
Nov 11, 2013, 10:24:48 AM11/11/13
to ra...@googlegroups.com, t...@timdown.co.uk
Hey Tim,

Thanks for your reply. 
I know that this module wasn't made primarily for such cases and I totally understand that this must be a complex topic. 
But I had to try it with CssClassApplier because it's so easy to use.

I've made some jQuery workarounds, so everything's fine now.

Thank you for your efforts!

Reply all
Reply to author
Forward
0 new messages