java JSONArray 使用範例

跟型別自動轉換的 javascript 與 python 相比, JSONArray 在 java 裡使用起來有點 卡卡的, 不是很直覺.

瀏覽 JsonArray, 並於每一個 array 裡, 再取出 json 範例,

Foreach with JSONArray and JSONObject
https://stackoverflow.com/questions/33215539/foreach-with-jsonarray-and-jsonobject

Seems like you can’t iterate through JSONArray with a for each. You can loop through your JSONArray like this:

for (int i=0; i < arr.length(); i++) {
    arr.getJSONObject(i);
}

存取 json object 範例:

import org.json.JSONObject;
public class Test {
    public static void main(String args[]){
       JSONObject jo = new JSONObject("{ \"abc\" : \"def\" }");
       System.out.println(jo.toString());
    }
}

json array 放進 json object 範例:

     JSONArray family = new JSONArray();
     JSONObject father = new JSONObject();
     father.put("name", "Max");
     father.put("age", 40);
     JSONObject mother = new JSONObject();
     mother.put("name","Honey");
     mother.put("age",41);
     family.add(father);
     family.add(mother);
     student.put("family", family);

json object 取出 json array

student.getJSONArray("family")

pass java variable in jsp:param

在 jsp 之間傳遞變數, 可以這樣做:

<%!  
    String str = "prerna";  
%>  

<jsp:include page="index.html">
      <jsp:param name="type1" value="<%=str%>" />  
</jsp:include>

或:

Using request.setAttribute() you can pass the Java variable to the JSP.

 <%  
    String str = "prerna";

    request.setAttribute("myVar",str);
  %>  

 <jsp:include page="index.html">
      <jsp:param name="type1" value="${myVar}" >
      </jsp:param>  
 </jsp:include>

資料來源:
https://stackoverflow.com/questions/5444083/pass-java-variable-in-jspparam

Include another JSP file

在JSP中,有兩種 include

<%@include file="includes/header.jsp" %>

What you’re doing is a static include. A static include is resolved at compile time, and may thus not use a parameter value, which is only known at execution time.

What you need is a dynamic include:

<jsp:include page="..." />

Note that you should use the JSP EL rather than scriptlets. It also seems that you’re implementing a central controller with index.jsp. You should use a servlet to do that instead, and dispatch to the appropriate JSP from this servlet. Or better, use an existing MVC framework like Stripes or Spring MVC.

  • 第一種, 沒有 page= 的include會在編譯時期(轉換成servlet)就將file include進來,最後只會有一個.class檔案.
  • 第二種, 有 page= 的include, 在編譯時期並不會被編譯,是在client request時,才會動態的去載入在去編譯。

如果要帶參數, You can use parameters like that

<jsp:include page='about.jsp'>
    <jsp:param name="articleId" value=""/>
</jsp:include>

and

in about.jsp you can take the paramter

<%String leftAds = request.getParameter("articleId");%>

You can use Include Directives

<%
 if(request.getParameter("p")!=null)
 { 
   String p = request.getParameter("p");
%>    

<%@include file="<%="includes/" + p +".jsp"%>"%>

<% 
 }
%>

or JSP Include Action

<%
 if(request.getParameter("p")!=null)
 { 
   String p = request.getParameter("p");
%>    

<jsp:include page="<%="includes/"+p+".jsp"%>"/>

<% 
 }
%>

資料來源:
https://stackoverflow.com/questions/9110148/include-another-jsp-file

How to Convert an SVG to an Image in the Browser?

在使用 selenium 取得網頁內容裡的圖片時,遇到圖片不是 bitmap, 而是 svg 時會出錯。

javascript error: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLCanvasElement or HTMLImageElement or HTMLVideoElement or ImageBitmap or OffscreenCanvas or SVGImageElement or VideoFrame)

服用下面的 sample 即可:

const svg = `
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="300" height="200">
   <rect width="100%" height="100%" fill="red" />
   <circle cx="150" cy="100" r="80" fill="green" />
   <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>
`
svgToPng(svg, (imgData) => {
  const pngImage = document.createElement('img');
  document.body.appendChild(pngImage);
  pngImage.src = imgData;
});
function svgToPng(svg, callback) {
  const url = getSvgUrl(svg);
  svgUrlToPng(url, (imgData) => {
    callback(imgData);
    URL.revokeObjectURL(url);
  });
}
function getSvgUrl(svg) {
  return URL.createObjectURL(new Blob([svg], {
    type: 'image/svg+xml'
  }));
}
function svgUrlToPng(svgUrl, callback) {
  const svgImage = document.createElement('img');
  document.body.appendChild(svgImage);
  svgImage.onload = () => {
    const canvas = document.createElement('canvas');
    canvas.width = svgImage.clientWidth;
    canvas.height = svgImage.clientHeight;
    const canvasCtx = canvas.getContext('2d');
    canvasCtx.drawImage(svgImage, 0, 0);
    const imgData = canvas.toDataURL('image/png');
    callback(imgData);
  };
  svgImage.src = svgUrl;
}

相關網頁

CanvasRenderingContext2D.drawImage()
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage

在前端使用 JavaScript 操作 Canvas 來合併 SVG(Scalable Vector Graphics)圖片
https://dotblogs.com.tw/supershowwei/2022/08/15/use-javascript-to-merge-svg-images-in-canvas

bootstrap sidebar menut items too long to wrap

如果是選有 icon 的顯示方式, 預設會 wrap 到 icon 下方, 例如:

解法:

.nav-item .nav-link { 
     display: flex;
 }

完整範例:

<li class="nav-item">
  <a class="nav-link d-flex" href="after.html">
    <i class="nav-icon fa fa-group align-self-center"></i>After school program
    <span class="badge badge-info align-self-start">337</span>
  </a>
</li>

資料來源:
https://github.com/coreui/coreui-free-bootstrap-admin-template/issues/478

jQuery disable/enable submit button

避免使用者重覆按某一個按鈕.

解法1:

$(document).ready(function() {
     $(':input[type="submit"]').prop('disabled', true);
     $('input[type="text"]').keyup(function() {
        if($(this).val() != '') {
           $(':input[type="submit"]').prop('disabled', false);
        }
     });
 });

解法2:

$(function() {
  $(":text").keypress(check_submit).each(function() {
    check_submit();
  });
});

function check_submit() {
  if ($(this).val().length == 0) {
    $(":submit").attr("disabled", true);
  } else {
    $(":submit").removeAttr("disabled");
  }
}

HTML

The “disabled” in <input type="button" disabled> in the markup is called a boolean attribute by the W3C.

HTML vs. DOM

Quote:

A property is in the DOM; an attribute is in the HTML that is parsed into the DOM.

https://stackoverflow.com/a/7572855/664132

jQuery

Related:

Nevertheless, the most important concept to remember about the checked attribute is that it does not correspond to the checked property. The attribute actually corresponds to the defaultChecked property and should be used only to set the initial value of the checkbox. The checked attribute value does not change with the state of the checkbox, while the checked property does. Therefore, the cross-browser-compatible way to determine if a checkbox is checked is to use the property.

Relevant:

Properties generally affect the dynamic state of a DOM element without changing the serialized HTML attribute. Examples include the value property of input elements, the disabled property of inputs and buttons, or the checked property of a checkbox. The .prop() method should be used to set disabled and checked instead of the .attr() method.

$( "input" ).prop( "disabled", false );

Summary

To […] change DOM properties such as the […] disabled state of form elements, use the .prop() method.

(http://api.jquery.com/attr/)

As for the disable on change part of the question: There is an event called “input”, but browser support is limited and it’s not a jQuery event, so jQuery won’t make it work. The change event works reliably, but is fired when the element loses focus. So one might combine the two (some people also listen for keyup and paste).

Here’s an untested piece of code to show what I mean:

$(document).ready(function() {
    var $submit = $('input[type="submit"]');
    $submit.prop('disabled', true);
    $('input[type="text"]').on('input change', function() { //'input change keyup paste'
        $submit.prop('disabled', !$(this).val().length);
    });
});

資料來源:
https://stackoverflow.com/questions/1594952/jquery-disable-enable-submit-button

How to Set focus to first text input in a bootstrap modal after shown

因為彈出的modal 就是要去填資料, 但每次都要多用滑鼠點一點, 覺得很麻煩, 希望彈出 modal 後, 可以讓游標停在第一個輸入欄位. 解法:

Your code is basically correct. But the event show.bs.modal is triggerede before the modal has been shown. You need to use shown.bs.modal event instead.

jQuery(function($) {
    $('#myModal').on('shown.bs.modal', function() {
        $('input[name="myInput"]').focus();
    });
});

For Bootstrap 2

modal.$el.on('shown', function () {
$('input:text:visible:first', this).focus();
});  

Update: For Bootstrap 3

$('#myModal').on('shown.bs.modal', function () {
    $('#textareaID').focus();
})  

========== Update ======

In response to a question, you can use this with multiple modals on the same page if you specify different data-targets, rename your modals IDs to match and update the IDs of the form input fields, and finally update your JS to match these new IDs:
see http://jsfiddle.net/panchroma/owtqhpzr/5/

HTML

...
<button ... data-target="#myModal1"> ... </button> 
... 
<!-- Modal 1 -->
<div class="modal fade" id="myModal1" ...>
... 

<div class="modal-body"> <textarea id="textareaID1" ...></textarea></div>

JS

$('#myModal1').on('shown.bs.modal', function() {
  $('#textareaID1').focus();
})

資料來源:
https://stackoverflow.com/questions/15247849/how-to-set-focus-to-first-text-input-in-a-bootstrap-modal-after-shown


實測, 上面的方法都無效, 應該是年代久遠, bootstrap 改版, 官方提供的解法:
https://getbootstrap.com/docs/5.3/components/modal/

const myModal = document.getElementById('myModal')
const myInput = document.getElementById('myInput')

myModal.addEventListener('shown.bs.modal', () => {
  myInput.focus()
})

How to return an html document from java servlet?

在某一個特定的網址, 想要顯示其他檔案裡的 html 內容.
https://stackoverflow.com/questions/17036130/how-to-return-an-html-document-from-java-servlet


You either print out the HTML from the Servlet itself (deprecated)

PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>My HTML Body</h1>");
out.println("</body></html>");

or, dispatch to an existing resource (servlet, jsp etc.) (called forwarding to a view) (preferred)

RequestDispatcher view = request.getRequestDispatcher("html/mypage.html");
view.forward(request, response);

The existing resource that you need your current HTTP request to get forwarded to does not need to be special in any way i.e. it’s written just like any other Servlet or JSP; the container handles the forwarding part seamlessly.

Just make sure you provide the correct path to the resource. For example, for a servlet the RequestDispatcher would need the correct URL pattern (as specified in your web.xml)

RequestDispatcher view = request.getRequestDispatcher("/url/pattern/of/servlet");

Also, note that the a RequestDispatcher can be retrieved from both ServletRequest and ServletContext with the difference that the former can take a relative path as well.

Reference:
http://docs.oracle.com/javaee/5/api/javax/servlet/RequestDispatcher.html

Sample Code

public class BlotServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
        // we do not set content type, headers, cookies etc.
        // resp.setContentType("text/html"); // while redirecting as
        // it would most likely result in an IllegalStateException

        // "/" is relative to the context root (your web-app name)
        RequestDispatcher view = req.getRequestDispatcher("/path/to/file.html");
        // don't add your web-app name to the path

        view.forward(req, resp);    
    }

}