2013-04-18 3 views
1

Я пытаюсь создать приложение букмарклета, которое анализирует информацию из Amazon, Etsy и JCrew и передает его в приложение списка пожеланий, встроенное в Rails. Мне удалось создать кнопку закладки, загружающую мой файл javascript в DOM, но, похоже, он не работает правильно и не передает данные в мое приложение. Или, может быть, мой javascript неисправен. Может ли кто-нибудь помочь мне выяснить, что я делаю неправильно? Я включил мой файл JS ниже:Сложность выполнения bookmarklet javascript

function() { 

function get_amazon_product_info() 
    { 
     var title_span = document.getElementById("btAsinTitle"); 
     var title = title_span.innerText; 

     var image_tag = document.getElementById("main-image"); 
     var image = image_tag.getAttribute("src"); 

     var price_span = document.getElementById("actualPriceValue"); 
     var price = price_span.innerText; 

     var product_info = { 
      title: title, 
      image: image, 
      price: price 
     } 
     return product_info 
    } 

function get_etsy_product_info() 
{ 
     var title_span = document.getElementById("item-title"); 
     var title = title_span.innerText; 

     var image_div = document.getElementById("fullimage_link1"); 
     var image_tag = image_div.getElementsByTagName("img"); 
     var image = image_tag[0].getAttribute("src"); 

     var price_div = document.getElementsByClassName("item-price"); 
     var price_span = price_div[0].getElementsByClassName("currency-value") 
     var price = price_span[0].innerText; 

     var product_info = { 
      title: title, 
      image: image, 
      price: price 
     } 
     return product_info 
} 

function get_jcrew_product_info() 
{ 
    var title_span = document.getElementById("pdp-title"); 
     var title = title_span.innerText; 

     var image_div = document.getElementsByClassName("prod_main_img"); 
     var image_tag = image_div[0].getElementsByTagName("img"); 
     var image = image_tag[0].getAttribute("src"); 

     //lame implementation -- need to be able to determine which radio button is checked. Finish later! 

     var price_div = document.getElementsByClassName("pdp-shapes"); 
     var price_span = price_div[0].getElementsByClassName("price") 
     var price = price_span[0].innerText; 

     var product_info = { 
      title: title, 
      image: image, 
      price: price 
     } 
     return product_info 
} 

function determine_params() 
{ 
     domain = document.domain; 
     if (domain == 'www.amazon.com') 
     { 
      get_amazon_product_info(); 
     } 
     else if (domain == 'www.etsy.com') 
     { 
      get_etsy_product_info(); 
     } 
     else if (domain == 'www.jcrew.com') 
     { 
      get_jcrew_product_info(); 
     } 
} 

function send_data(product_info) 
{   
    var link_url = document.URL; 
    var http = new XMLHttpRequest(); 
    var url = "http://max-miller.local:3000/add_product"; 
    var params = "title=" + product_info[title] + "&image=" + product_info[image] + "&price=" + product_info[price] + "&link_url=" + link_url; 
    http.open("POST", url , true); 

    //Send the proper header information along with the request 
    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
    http.setRequestHeader("Content-length", params.length); 
    http.setRequestHeader("Connection", "close"); 

    http.onreadystatechange = function() { 
     if(http.readyState == 4 && http.status == 200) { 
      alert(http.responseText); 
     } 
    } 

    http.send(params); 
} 

determine_params(); 
send_data(product_info); 

}

+0

+1 для http.onreadystatechange; я также попробую это; мне никогда не приходило в голову это –

+0

Это весь файл? ... Я не понимаю, почему он * выполнил бы. Если это так, у вас есть закрытие, которое никогда не выполняется. – svidgen

+0

Кроме того, если этот букмарклет предназначен для выполнения в доменах, отличных от 'max-miller.local: 3000', я думаю, вам понадобится альтернатива' XMLHttpRequest', поскольку скрипт будет выполняться в контексте * * домен. – svidgen

ответ

0

надеюсь, что это помогает:

Я никогда не посылала данные, как вы делали, с http.sed(data)

Однако, я создал сценарий элемент в разделе главы, когда мне нужно что-то с сервера;

всегда использовать json.stringify, это может быть одна из причин того, что ваше приложение не отправляет данные

, а также if (s.length >= 2000) быть осторожными при использовании моего решения, потому что вы не можете отправить/получить бесконечные данные через 1 запрос

так:

function createElementScript(src) 
    { 

     var script = document.createElement("script"); 
     script.type = 'text/javascript'; 
     script.src = src; 
     //console.log("SRC: "+src); 
     var header = document.getElementsByTagName("head"); 
     header[0].appendChild(script); 
    } 

где src создается как:

var s = JSON.stringify({'url': location.href, 
            'title': document.getElementById('linkbook_article_title').value, 
            'description': document.getElementById('linkbook_article_textarea').value 
           }); 
           if (s.length >= 2000) { 
            alert('Payload length is over 2000, action may fail.'); 
           } 
           createElementScript(apiURL + "/FollowProduct?input=" + encodeURIComponent(s)); 

весь мой букмарклет, возможно, он поможет вам улучшить вашу; я использовал одноплодный шаблон, просто чтобы убедиться, что я не переустановите букмарклет, если пользователь нажимает несколько раз на букмарклете и я также хотел, чтобы инкапсулировать все данные

<?php if (false) { ?><script><?php } ?> 
    var LinkbookClass = LinkbookClass ? LinkbookClass : function() { 

     var assetsURL = '<?= $this->getAssetsUrl(); ?>'; 
     var apiURL = '<?= Yii::app()->createAbsoluteUrl($this->module->id . '/' . $this->id . '/'); ?>'; 
     var imgsList = new Array(); 
     var ImgsListImgID = 0; 
     //all the images found on the webpage 
     var images = 0; 
     var imgsListHeightWidth = []; 
     var isHighlighting = false; 
     var versionStatus; 
     var flag1 = false; 
     var flag2 = false; 
     var precedentObj = null; 
     var overlay, 
       current, 
       handler; 
     var extractHL; 
     var name = false, price = false, image = false; 
     //do we save logs ? 
     var consoleLog = true; 
     var version_popup; 
     var f = function() 
     { 
      createElementScript(assetsURL + '/sizzle.js?x=<?= $this->module->params['interface_version']; ?>'); 
      createElementScript(assetsURL + '/xpath.js?x=<?= rand(1, 10000000); ?>'); 
      //LinkbookPluginCollection.run(); 

      var popupdividreset = "linkbookreset"; 
      var DOCreset = document.getElementById(popupdividreset); 
      if (DOCreset != null) { 
       return false; 
      } 

      var popupdivid = "linkbookdetails"; 
      var DOC = document.getElementById(popupdivid); 
      if (DOC != null) { 
       return false; 
      } 

      //load css file, force a reload/recache 
      addCSS(assetsURL + '/linkbook.css?x=<?= rand(1, 10000000); ?>'); 
      var divreset = document.createElement("div"); 
      divreset.id = popupdividreset; 
      var div = document.createElement("div"); 
      div.id = popupdivid; 
      //this will highlight the DOM element that you are hovering 
      var divhighlight = document.createElement("div"); 
      divhighlight.id = "overlayhighlightlinkbook"; 
      var divOutside = document.createElement("div"); 
      divOutside.id = "LinkbookOverlay"; 
      var divLinkbook = document.createElement("divCloseAffair"); 
      divLinkbook.id = "divLinkbook"; 
      var str = '<div id="divemptylinkbook"></div>'; 
      str += divForm('none', div.id, images); 
      str += divLogin('none', div.id); 
      str += divDetails('none', div.id); 
      str += divSuccess('none', div.id); 
      str += divBroken('none', div.id); 
      div.innerHTML = str; 
      divreset.appendChild(div); 
      //not used anymore 
      //document.body.insertBefore(divreset, document.body.firstChild); 

      divOutside.innerHTML = ""; 
      //inserting the DOM div blank element imediatly after body tag 
      divhighlight.innerHTML = ""; 
      divLinkbook.appendChild(divhighlight); 
      divLinkbook.appendChild(divOutside); 
      divLinkbook.appendChild(divreset); 
      document.body.insertBefore(divLinkbook, document.body.firstChild); 
     }; 
     function addCSS(url) { 
      var headID = document.getElementsByTagName("head")[0]; 
      var cssNode = document.createElement('link'); 
      cssNode.type = 'text/css'; 
      cssNode.rel = 'stylesheet'; 
      cssNode.href = url; 
      cssNode.media = 'screen'; 
      headID.appendChild(cssNode); 
     } 
     ; 
     function divLogin(displayTarget, div_id) 
     { 

      return '<?php $this->renderHTMLtoJS('login', array('js' => array('displayTarget', 'div_id', 'assetsURL'))); ?>'; 
     } 
     ; 
     function divForm(displayTarget, div_id, images) 
     { 

      return '<?php $this->renderHTMLtoJS('form', array('js' => array('displayTarget', 'div_id', 'images', 'assetsURL'), 'url' => $url, 'follower' => $follower)); ?>'; 
     } 
     ; 
     function divBroken(displayTarget, div_id) 
     { 

      return '<?php $this->renderHTMLtoJS('report_broken_url', array('js' => array('displayTarget', 'div_id', 'assetsURL'))); ?>'; 
     } 
     ; 
     function divSuccess(displayTarget, div_id) 
     { 

      return '<?php $this->renderHTMLtoJS('success', array('js' => array('displayTarget', 'div_id', 'assetsURL'))); ?>'; 
     } 
     ; 
     function divDetails(displayTarget, div_id) 
     { 
      return '<?php $this->renderHTMLtoJS('details', array('js' => array('displayTarget', 'div_id', 'assetsURL'), 'url' => $url, 'follower' => $follower)); ?>'; 
     } 
     ; 
     function createElementScript(src) 
     { 

      var script = document.createElement("script"); 
      script.type = 'text/javascript'; 
      script.src = src; 
      //console.log("SRC: "+src); 
      var header = document.getElementsByTagName("head"); 
      header[0].appendChild(script); 
     } 
     ; 
     function hideAllDivs() { 
      var a = ['LinkbookParrentLogin', 'LinkbookParrentDetails', 'LinkbookParrentForm']; 
      for (x in a) { 
       var d = document.getElementById(a[x]); 
       if (d) { 
        d.style.display = 'none'; 
       } 
      } 
     } 
     ; 
     function divGallery(displayTarget, div_id) 
     { 
      return '<?php $this->renderHTMLtoJS('gallery', array('js' => array('displayTarget', 'div_id', 'assetsURL'))); ?>'; 
     } 
     ; 
     f.prototype = { 
      labelEdit: function() 
      { 
       if (document.getElementById('form_selected_product_name_Linkbook_input').style.display == 'none') 
       { 
        document.getElementById('form_selected_product_name_Linkbook_input').style.display = document.getElementById("divemptylinkbook").style.display; 
        document.getElementById('form_selected_product_name_Linkbook_span').style.display = 'none'; 
        document.getElementById('Linkbook_labelEdit').style.display = 'none'; 
        document.getElementById('form_selected_product_name_Linkbook_input').value = document.getElementById('form_selected_product_name_Linkbook_span').innerHTML; 
        document.getElementById('form_selected_product_name_Linkbook_input').focus(); 
       } 
      }, 
      get_article_title: function() 
      { 
       if (document.title) 
        document.getElementById('linkbook_article_title').value = document.title; 
       else 
        document.getElementById('linkbook_article_title').value = location.href; 
      }, 
      get_article_description: function() 
      { 
       if (document.getElementsByName('description')[0]) 
       { 
        if (document.getElementsByName('description')[0].getAttribute('content')) 
         document.getElementById('linkbook_article_textarea').value = document.getElementsByName('description')[0].getAttribute('content'); 
        else 
         document.getElementById('linkbook_article_textarea').value = 'null'; 
       } 
       else 
        document.getElementById('linkbook_article_textarea').value = 'null'; 
      }, 
      init_after_login: function(is_product) 
      { 
       this.showDiv('LinkbookParrentForm'); 
      }, 
      init: function() { 
       //console.log('init'); 
       this.get_article_title(); 
       this.get_article_description(); 
       if (<?php 
    if (Yii::app()->user->isGuest) 
     echo 'true'; 
    else 
     echo 'false'; 
?>) { 
        this.showDiv('LinkbookParrentLogin'); 
       } else { 

        Linkbook.init_after_login(<?php 
    if (empty($product)) 
     echo 'false'; 
    else 
     echo 'true'; 
?>); 
       } 
      }, 
      showDiv: function(divId) { 
       var d = document.getElementById(divId); 
       if (d) { 
        hideAllDivs(); 
        d.style.display = document.getElementById("divemptylinkbook").style.display; 
       } 
      }, 
      actionSubmit: function(formID, e) 
      { 
       //alert(formID+'click'); 
       if (formID == 1) 
        Linkbook.outBound("login"); 
       if (formID == 2) 
        Linkbook.outBound("follow"); 
       e.preventDefault(); 
      }, 
      toggleItem: function(id) { 
       var item = document.getElementById(id); 
       if (item) { 
        var parent = item.parentNode; 
        parent.removeChild(item); 
       } 
      }, 
      hideDivs: function() { 
       hideAllDivs(); 
      }, 
      //all the data that has been send from the server to the bookmarlet passed thru this method 
      //inBound has 2 parameters, because we need to know the action and the result value 
      inBound: function(action, data) 
      { 

       try { 
        //console.log(data); 
        if (parseInt(data.code) < 0) { 
         //system error 
         alert('Internal error!'); 
         return; 
        } 
        switch (action) 
        { 
         case 'login': 
          //console.log('data code: '+data.code); 
          if (data.code != 0) { 
           // show error 
           document.getElementById('LinkbookLoginError').innerHTML = data.message; 
          } else { 
           //console.log(data.login.json_order); 
           //repopulating plugin collection after login action; 
           //LinkbookPluginCollection.cleanup();//cleanup needed 
           //LinkbookPluginCollection.order = data.login.json_order;//repopulation 
           //LinkbookPluginCollection.run(); 
           //console.log('new data'+data.login.product); 
           //this.showDiv('LinkbookParrentForm'); 
           //console.log(data.login.product.product_name && data.login.product.product_name.length>0); 
           Linkbook.init_after_login(data.login.product.product_name && data.login.product.product_name.length > 0); 
          } 
          break; 
         case 'logout': 
          hideAllDivs(); 
          this.showDiv('LinkbookParrentLogin'); 
          break; 
         case 'bookmarklet': 
          alert('Bookmarklet error'); 
          break; 
         case 'follow': 
          if (data.code != 0) 
          { 
           document.getElementById('form_error_Linkbook').innerHTML = data.message; 
          } 
          else 
          { 
           this.showDiv('LinkbookParrentSuccess'); 
          } 
          break; 
         default: 
          alert('Unknown inBound action: ' + action); 
          break; 
        } 
       } catch (err) { 
        if (consoleLog) { 
         //console.log(err.toString()); 
        } 
        alert('Something went wrong, server returned invalid message!'); 
       } 
      }, //end f inBound() 
      //method used to transfer the data from the bookmarklet to the server 
      //outBound needs to know only the action, the parameters will be contructed, ex. : ?action=x&... 
      outBound: function(action) 
      { 
       try { 
        switch (action) 
        {//start switch 
         case 'logout': 
          createElementScript(apiURL + '/MakeLogout'); 
          break; 
         case 'login': 
          if (document.getElementById("form_remember").value == 'on') 
           form_remember_Linkbook = 1; 
          else 
           form_remember_Linkbook = 0; 
          createElementScript(apiURL + '/MakeLogin/email/' + document.getElementById("form_email").value + '/password/' + document.getElementById("form_password").value + '/remember/' + form_remember_Linkbook + '?url=' + encodeURIComponent(location.href)); 
          break; 
         case 'follow': 
          if (true) 
          { 
           //document.getElementById('form_error_Linkbook').innerHTML = ''; 
           var s = JSON.stringify({'url': location.href, 
            'title': document.getElementById('linkbook_article_title').value, 
            'description': document.getElementById('linkbook_article_textarea').value 
           }); 
           if (s.length >= 2000) { 
            alert('Payload length is over 2000, action may fail.'); 
           } 
           createElementScript(apiURL + "/FollowProduct?input=" + encodeURIComponent(s)); 
          } else { 
           // put error message on screen 
           document.getElementById('form_error_Linkbook').innerHTML = 'error'; 
          } 
          break; 
         case 'report_broken_url': 
          this.showDiv('LinkbookParrentBroken'); 
          //var s = JSON.stringify(LinkbookPluginCollection); 
          if (s.length >= 2000) { 
           alert('Payload length is over 2000, action may fail.'); 
          } 
          createElementScript(apiURL + "/ReportBrokenUrl?input=" + encodeURIComponent(s)); 
          break; 
         default: 
          alert('Unknown outBound action: ' + action); 
          break; 
        }//end switch 
       } 
       catch (err) { 
        if (consoleLog) { 
         //console.log(err.toString()); 
        } 
        alert('Something went wrong, couldn\'t prepare data!'); 
       } 


      }//end f outBound() 
     } 
     return f; 
    }(); 
    var Linkbook = new LinkbookClass(); 
    Linkbook.init(); 
0

Как отмечался в моих комментариях, есть две проблемы, которые я вижу с вашим кодом as-is.

Первый, ваше закрытие никогда не выполняется - на самом деле оно является синтаксически неправильным как есть. В консоли браузера, это разница между этим примером:

function() { console.log('something'); } 

И это одна:

(function() { console.log('something'); })(); 

Второй, XMLHttpRequest будет работать только в контексте домена страницы. (Сценарий не получает особых привилегий для домена, из которого он приходит.) Таким образом, учитывая характер вашего скрипта, он выглядит так: max-miller.local:3000: не предполагаемый домен исполнения, и запрос не будет выполнен.

Посмотрите на JSONP-подобные решения.

Смежные вопросы