How to stop PNotify button click fire parent click handler

Permalink
I have an image map with a click event which places a marker on it:
<div id="map_wrapper">
  <div id="map">
    <img src="map.png" />
  </div>
</div>
...
$('#map').on('click', function(e){
    alert(e.target.id); // this is the image inside 'map'
    alert(e.currentTarget.id); // this is the 'map'
    var pin = $('<div class="pin"></div>');
    $('#map_wrapper').append(pin);

then clicking the pin opens a PNotify popup with a text input and a save button, clicking on which appends the entered text to the wrapper:
$('#map_wrapper').on('click', '.pin', function(e){
    var id = this.id;
    show_notice(id);
});
function show_notice(id){
    notice = new PNotify({
        text: form,
        ...
    });
    $('form [name=save]').off('click').on('click', function(e){
        e.preventDefault();
        e.stopImmediatePropagation();
        e.stopPropagation();
        $('#' + id).append('<p class="pin-text hidden">' + $.trim($('#pin_text').val()) + '</p>');
        notice.remove();

I can't figure out what causes adding (doubling) new pins to the map on Save button click. I alerted 'e.target.id' and 'e.currentTarget.id' - these pop up after clicking on the map, but nothing happens (no alert) after clicking the Save button on the notice form but the pins actually append to the map...

How do I stop the Save click adding new pins to the map?

linuxoid
 
mnakalay replied on at Permalink Reply
mnakalay
I'm not sure it's going to help but you could try this. Instead of appending your pin on the form's save button's click event, try doing it on the form submit event directly
linuxoid replied on at Permalink Reply
linuxoid
Not quite what happens. A pin is appended on clicking the map. The notice is popped up on clicking the pin. The text from the notice form is appended as <p> on clicking the Save button.

If I use a submit button, where will the form submit to?

I forgot to mention, it only appends the pins if the text input field has text, if it's empty, it appends an empty <p>, but it does NOT append the pins. This is so weird! Why would it do that? I could understand if it appended pins on clicking Save regardless, but why only with text? I have no clue what may cause that.
mnakalay replied on at Permalink Reply
mnakalay
in the code above I see where the text paragraph is added but I don't see where the pin is added so I can't say.

If you are not going to use a submit button then you don't really need a form. Input boxes can live outside of a form.

If, on the other hand, you want to use the form submit event then you need a form (duh!) but you don't need to submit to anything since you are going to catch the event and use it for your purpose.

$(yourform).on('submit', function(evt) {
    evt.preventDefault();
    // do your stuff
});
linuxoid replied on at Permalink Reply
linuxoid
This is where the pin is added:
$('#map').on('click', function(e){
    alert(e.target.id); // this is the image inside 'map'
    alert(e.currentTarget.id); // this is the 'map'
    var pin = $('<div class="pin"></div>');
    $('#map_wrapper').append(pin);

I've already tried the submit event, but the pins are still added! Looks like the click event is caught by the map anyway. Weird!

Is there any way to allow appending pins ONLY if the map is clicked, nothing else?
mnakalay replied on at Permalink Reply
mnakalay
I just noticed something wrong with your code in your show_notice function you have
e.preventDefault();
    e.stopImmediatePropagation();
    e.stopPropagation();


but e is not defined in that function so you should put those 3 lines in the click function instead
linuxoid replied on at Permalink Reply
linuxoid
Sorry, that's a typo, they're actually inside the click function, I've corrected the original post.
linuxoid replied on at Permalink Reply
linuxoid
After further investigation, what happens is:
- pin coordinates are stored in the DB
- Add block form loads, then the map image loads, then the pins and are placed at the coordinates
- I move the pins (just for example), click on one, a notice pops up, I enter text in the form input and click the Save button
- The notice closes AND 2 new pins appear at the exact same locations as those loaded from the DB
- The new pins are added ONLY if text is entered. If the text input is empty, no pins are added

There is NO code to do that. The only 2 places where the pins are appended to the map are the map image load function and the map click function - that's it!

How can the PNotify button add the pins?
mnakalay replied on at Permalink Reply
mnakalay
At this point, I have no idea. Could you share your whole block so I can test myself?
mnakalay replied on at Permalink Reply
mnakalay
in this part
$('#map_wrapper').on('click', '.pin', function(e){
    var id = this.id;
    show_notice(id);
});

where do you get the id from since this represent the pin and the pin doesn't have an id?
linuxoid replied on at Permalink Reply
linuxoid
The id = this.id which returns the pin div id. The pin does have an id, I set it with
pin.uniqueId();
mnakalay replied on at Permalink Reply
mnakalay
ah ok. You didn't show that bit in your original post I think.

Anyway, I just got your PM I'll have a look.
mnakalay replied on at Permalink Reply
mnakalay
in your form.php, around line 241 you have
$(document).bind('change', 'input[name="pictureID"]', function() {

That's not the right way to do it and as a result, any time you change anything in your whole document, that code is triggered, breaking havoc.
To test, put a breakpoint on the line right after in your browser's developer tool then open your pNotify window, enter your text then click somewhere else and that code will be triggered.

The reason we use that kind of code is when we want to hook on an event for a DOM element that doesn't exist yet. For instance, when you do it like that for your pins it makes sense because you are going to add them dynamically.
But your pictureID element is not added dinamically so just use the event stuff normally with the code below which for me solved the problem.
$('input[name="pictureID"]').bind('change', function() {


There are other things that seem wrong in your code. For instance, why, when you are adding to the picture your pins saved in the DB do you give them a new unique ID? you saved their original ID, why don't you re-use it?
linuxoid replied on at Permalink Reply
linuxoid
That code didn't work for me. When I select an image from the file manager it's not loaded.

I only use the pin id while in edit mode, I don't need exact values. I only store the id for testing.
mnakalay replied on at Permalink Reply
mnakalay
Sorry I didn't test what happens when you select the image with the manager. I followed your steps to reproduce the error so during my testing the image was already selected and I know that piece of code is responsible for the problems you're having.

Also, I believe the manager will throw an event when an image is selected and you should use that instead. Just look through the core code to see how they do it.
linuxoid replied on at Permalink Reply
linuxoid
I couldn't find any documentation on the ConcreteFileManager. Do you have a link?

https://documentation.concrete5.org/api/class-Concrete.Core.Applicat...

Uh Oh!
We couldn't find the page you were looking for.
mnakalay replied on at Permalink Reply
mnakalay
Like I said look through the code. Specifically have a look a form_setup_html.php in the image_slider block, around line 39. You will see how they launch the file manager and how they use ConcreteFileManager.getFileDetails as a callback
linuxoid replied on at Permalink Reply
linuxoid
I basically do the same thing. But the image slider form only loads thumbnails, I need to load the actual image.
mnakalay replied on at Permalink Reply
mnakalay
I don't know why you're saying that. The point is not what you are getting, the point is how you are getting it.

The way you do it doesn't work. It creates problems, it even creates extra pins on the image if you take certain actions.

The way the slider does it ensures the code is only called when needed and it works.

What's important here is how it is called. After that feel totally free to modify what's inside to your liking.

Having said so I don't see a difference. You get your image exactly the same way it's done with the slider except you use file.url instead of file.resultsThumbnailImg. All you need to change is that nasty on change event that's being called for too often and breaks everything
linuxoid replied on at Permalink Reply
linuxoid
I've simply replaced the lot for
echo '<div class="ccm-pick-slide-image ccm-pick-slide-image-' . $bID . '"></div>';
...
var attachFileManagerLaunch = function($obj) {
    $obj.click(function() {
        var oldLauncher = $(this);
        ConcreteFileManager.launchDialog(function(data) {
            ConcreteFileManager.getFileDetails(data.fID, function(r) {
                jQuery.fn.dialog.hideLoader();
                var file = r.files[0];
                oldLauncher.html(file.resultsThumbnailImg);
                oldLauncher.next('.image-fID').val(file.fID);
            });
        });
    });
};

and it says "ReferenceError: ConcreteFileManager is not defined"
linuxoid replied on at Permalink Reply
linuxoid
But that code above works if I put this on the form:
echo $al->image('picture', 'pictureID', t('Select picture') . ' <i class="fa fa-picture-o"></i>', $pic);

So looks like it's only working with the file picker on the form. I can't find how they get away without it in the slide block.
mnakalay replied on at Permalink Reply
mnakalay
$this->requireAsset('core/file-manager');
linuxoid replied on at Permalink Reply
linuxoid
You're the man!!! Thanks a lot! That worked )))

Would you know how to make the file manger to open the menu rather than going straight to pick a file? I need to process the clear picture event somehow.
mnakalay replied on at Permalink Reply
mnakalay
all I know is, using the image picker, when an image is selected, if you click on the picker you will see the menu instead of opening the manager. If that's not what's happening then something else is wrong.
linuxoid replied on at Permalink Reply 1 Attachment
linuxoid
No, clicking the picker goes straight to the file manager, no menu pops up. And this is exactly the same behavior in the Image Slider block.

Would anyone know how to show the same menu when clicking on the link as in the Image block picker (see attached image)?
mnakalay replied on at Permalink Reply
mnakalay
the image block uses the normal core image selector
$al = $app->make('helper/concrete/asset_library');
echo $al->image('ccm-b-image', 'fID', t('Choose Image'), $bf);

That will do what you want BUT then you don't control the JavaScript and your custom stuff might not work.

I suggest you go have a look at what's happening in the image() function in helper/concrete/asset_library and go from there