zwwcn

Just another WordPress.com site

Category Archives: JavaScript

JQuery notes

  1. How to add listener for html content loaded by ajax call?

    Bind on a non-dynamic parent container using .on()

    $('.some-parent-class').on('click', '.element', function() {
      // DO STUFF!
    });
  2. AddClass function

      AddClass function always check exisitng classes before adding new one, so we don’t need to check duplicate classes

     3. Find function

       The .find() and .children() methods are similar, except that the latter only travels a single level down the DOM tree

     4. text() and textarea

       The .text() method cannot be used on form inputs or scripts. To set or get the text value of input or textarea elements, use the .val() method

      5. checkbox and prop

$('.myCheckbox').prop('checked', true);
$('.myCheckbox').prop('checked', false);

      6. toggle

Quick way to switch show/hide, checked/unchecked state

$('#checkBoxId').click(function() {
    $("#otherCheckbox").toggle(this.checked);
});

       7. event.preventDefault()

Cancel the default action (navigation) of the click, this is used when we only want to trigger a js function but don’t want the page navagation.

 

access javascript object property using variable

I want to assign data to a js object as a property, but the new property name is dynamic.

The bracket notation should be used here:

var apiDynamicString = "dynamicStringFromOtherFunction";

var apiDynamicData ="somedata...";

example.data[apiDynamicString] = apiDynamicData ;

Then you can access the property this way:

console.log(example.data[apiDynamicString]);

OR (if you know the variable value)

console.log(example.data.dynamicStringFromOtherFunction);

javascript onclick event not working in chrome

The onclick event for select option is not triggered in chrome. We need to fire the onchange event on the select component.

<select class="select-one-group-select">
 <option class="select-one-group-option" value="option1">option 1</option>
 <option class="select-one-group-option"  value="option2">option 2</option>
 <option class="select-one-group-option"  value="option3">option 3</option>
</select>

This doesn’t work:

	$(".select-one-group-option").click(function() {
		showFilters(parseInt(this.value));
	});

 

This solve the problem:

	$(".select-one-group-select").change(function() {
		showFilters(parseInt(this.value));
	});

Read photo taken date from image

For Java, I use metadata-extractor:

Metadata metadata = ImageMetadataReader.readMetadata( item.getInputStream());
ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
if(date != null){
    file.setPhotoTakenDate(date);
}

For front end, I use exif-js:

window.resolveLocalFileSystemURL(attachmentInfo.fileSource, (fileEntry) ->
                fileEntry.file((file) ->
                    EXIF.getData(file, ->
                    	
                        galleryPhotoTakenDate = EXIF.getTag(this,"DateTimeOriginal");
                      
                        cameraPhotoTakenDate = this.lastModifiedDate;

                        if photoFromCamera
                            if typeof cameraPhotoTakenDate != 'undefined'
                                #photo taken from camera
                                attachmentInfo.photoTakenDate = moment(cameraPhotoTakenDate).format("YYYY:MM:DD HH:mm:SS")
                        else
                            if typeof galleryPhotoTakenDate != 'undefined'
                                #photo taken from gallery
                                attachmentInfo.photoTakenDate = galleryPhotoTakenDate 
                            
                    )                    
                )
                    
            )

debug JQuery script loaded by getscript function

When loading js function with JQuery getScript function, we can’t debug it becuase it’s not in DOM. The following js function add the loaded js function into DOM and solve the problem.

var loadScript = function (path) {
    var result = $.Deferred(),
        script = document.createElement("script");
    script.async = "async";
    script.type = "text/javascript";
    script.src = path;
    script.onload = script.onreadystatechange = function(_, isAbort) {
        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
            if (isAbort)
                result.reject();
            else
                result.resolve();
        }
    };
    script.onerror = function () { result.reject(); };
    $("head")[0].appendChild(script);
    return result.promise();
};

ref from :http://balpha.de/2011/10/jquery-script-insertion-and-its-consequences-for-debugging/

Multiple Canvas only draw the last one

I have five canvas on the page, The following code is supposed to read the image data from hidden input field and draw image to the correspoding canvas. but it only draw the last one.

$('.signatureField').each(function() {					   
	if($(this).children("input").val()!=""){
		canvas = $(this).children('canvas').get(0);
		ctx = canvas.getContext('2d');
		testImage = new Image();

		testImage.onload=function(){				
			ctx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,canvas.width,canvas.height);
		}
						
		testImage.src="data:image/png;base64,"+$(this).children("input").val();
	}						
})

Adding “var” to ctx solves the problem.What that does is to declare ctx as local variable in each loop, so they don’t share the same convas context.

$('.signatureField').each(function() {					   
	if($(this).children("input").val()!=""){
		var canvas = $(this).children('canvas').get(0);
		var ctx = canvas.getContext('2d');
		var testImage = new Image();

		testImage.onload=function(){				
			ctx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,canvas.width,canvas.height);
		}
						
		testImage.src="data:image/png;base64,"+$(this).children("input").val();
	}
})

Then I have the following code in CoffeeScript, unfortunately, it only draw the last canvas. Here I use apostrophe to declare canvas context as local variable. Also added an empty return at the end of the function to avoid CoffeeScript implicit return.

checklist.loadExistingSignature = (fields) ->
    for field in fields
        if field.type='signature' and field.value.length>0
            `var fieldCanvas = $('#' + field.id).get(0)`
            `var canvastx = fieldCanvas.getContext('2d')`
            `var testImage = new Image()`
            
            testImage.onload = ->
            	canvastx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,fieldCanvas.width,fieldCanvas.height);
            	return
            testImage.src = "data:image/png;base64," + field.value;
    return

To solve this problem, we need to add a javascript closure. In CoffeeScript , it’s the do function

checklist.loadExistingSignature = (fields) ->
    for field in fields
        if field.type='signature' and field.value.length>0
            `var fieldCanvas = $('#' + field.id).get(0)`
            `var canvastx = fieldCanvas.getContext('2d')`
            `var testImage = new Image()`
            do (canvastx, testImage) ->
            	testImage.onload = ->
            		canvastx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,fieldCanvas.width,fieldCanvas.height);
            		return
            	return
            testImage.src = "data:image/png;base64," + field.value;
    return

And the javascript version:

for (var i = 1; i < 5; i++) {
    var ctx = document.getElementById('canvas-' + i).getContext('2d'),
        image = new Image();
    (function(ctx, image) {
        image.onload = function() {
            ctx.drawImage(image, 0, 0);
        }
        image.src = images[(i - 1)];
    })(ctx, image);
}

ref for javascript closure in loop: http://www.mennovanslooten.nl/blog/post/62

JSF execute javascript after ajax call

To Execute js script after the f:ajax call

<h:selectOneMenu id="checklist" value="#{checklistReportAction.checklist}" required="true">
      <s:selectItems value="#{checklistReportAction.checklists}" var="_checklist"
        label="#{_checklist.name}" noSelectionLabel="Select Checklist..."/>
        <s:convertEntity />							 	
	<f:ajax  render="filterPanel checklistFieldPanel" listener="#{checklistReportAction.selectListener}" event="change" execute="@this" onevent="showCheckBox"/>
	</h:selectOneMenu>

The above code will call showCheckbox function after user change value for the dropdown list

CDATA and javascript

&& are not valid characters in XML so they are also not valid for Facelets as well.
Use script in CDATA to get full javascript support in Facelets . CDATA is used like this :

 

<script>
<![CDATA[
function check(){
if (isCondition1 &&  !isCondition2){
alert(“Please input a valid number!”)
}
}
]]>
</script>

WebRemote and Seam

Step 1: add webremote annotation for the specific method in local interface

@Local
public interface ProspectController extends StatefulController {

@WebRemote
public String createNewProspect();

}

Step 2:  create the javascript function

function showProspectPopUp(modelPanel,id){
Seam.Remoting.getContext().setConversationId(id);   //this is important: make sure the remote call is in the same conversation
Seam.Component.getInstance(“prospectController”).createNewProspect(null,exceptionHandler);
Richfaces.showModalPanel(modelPanel);
}

Step 3:  in jsf page, add the following:

<ui:define name=”js”>
<s:remote include=”prospectController”/>
<onepl:javascript src=”/js/main.js” cachebusting=”true”/>   //where the javascript function locates
</ui:define>

<h:outputLink onclick=”showProspectPopUp(‘prospPanel’,#{conversation.id});return false;”  value=””>test </h:outputLink>